aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin')
-rw-r--r--src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt8
-rw-r--r--src/main/kotlin/features/inventory/CraftingOverlay.kt20
-rw-r--r--src/main/kotlin/gui/entity/EntityWidget.kt35
-rw-r--r--src/main/kotlin/gui/entity/ModifyEquipment.kt70
-rw-r--r--src/main/kotlin/rei/FirmamentReiPlugin.kt142
-rw-r--r--src/main/kotlin/rei/NEUItemEntryRenderer.kt186
-rw-r--r--src/main/kotlin/rei/NEUItemEntrySerializer.kt29
-rw-r--r--src/main/kotlin/rei/SBItemEntryDefinition.kt254
-rw-r--r--src/main/kotlin/rei/SkyblockCraftingRecipeDynamicGenerator.kt64
-rw-r--r--src/main/kotlin/rei/SkyblockItemIdFocusedStackProvider.kt25
-rw-r--r--src/main/kotlin/rei/math.kt10
-rw-r--r--src/main/kotlin/rei/recipes/SBCraftingRecipe.kt55
-rw-r--r--src/main/kotlin/rei/recipes/SBEssenceUpgradeRecipe.kt62
-rw-r--r--src/main/kotlin/rei/recipes/SBForgeRecipe.kt71
-rw-r--r--src/main/kotlin/rei/recipes/SBKatRecipe.kt224
-rw-r--r--src/main/kotlin/rei/recipes/SBMobDropRecipe.kt108
-rw-r--r--src/main/kotlin/rei/recipes/SBRecipe.kt31
-rw-r--r--src/main/kotlin/repo/PetData.kt24
-rw-r--r--src/main/kotlin/repo/RepoManager.kt5
-rw-r--r--src/main/kotlin/repo/SBItemStack.kt165
-rw-r--r--src/main/kotlin/util/HoveredItemStack.kt42
-rw-r--r--src/main/kotlin/util/SkyblockId.kt5
-rw-r--r--src/main/kotlin/util/compatloader/CompatLoader.kt3
23 files changed, 266 insertions, 1372 deletions
diff --git a/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt b/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt
index 825cd6c..5151862 100644
--- a/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt
+++ b/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt
@@ -15,8 +15,8 @@ import moe.nea.firmament.events.WorldReadyEvent
import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.gui.hud.MoulConfigHud
-import moe.nea.firmament.rei.SBItemEntryDefinition
import moe.nea.firmament.repo.ItemNameLookup
+import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SHORT_NUMBER_FORMAT
import moe.nea.firmament.util.SkyblockId
@@ -197,9 +197,9 @@ object AnniversaryFeatures : FirmamentFeature {
}
val itemStack = if (backedBy is Reward.Items) {
- SBItemEntryDefinition.getEntry(backedBy.item, backedBy.amount)
+ SBItemStack(backedBy.item, backedBy.amount)
} else {
- SBItemEntryDefinition.getEntry(SkyblockId.NULL)
+ SBItemStack(SkyblockId.NULL)
}
@Bind
@@ -207,7 +207,7 @@ object AnniversaryFeatures : FirmamentFeature {
return when (backedBy) {
is Reward.Coins -> "Coins"
is Reward.EXP -> backedBy.skill
- is Reward.Items -> itemStack.value.asItemStack().name.string
+ is Reward.Items -> itemStack.asImmutableItemStack().name.string
is Reward.Unknown -> backedBy.text
}
}
diff --git a/src/main/kotlin/features/inventory/CraftingOverlay.kt b/src/main/kotlin/features/inventory/CraftingOverlay.kt
index 8e75478..a958e25 100644
--- a/src/main/kotlin/features/inventory/CraftingOverlay.kt
+++ b/src/main/kotlin/features/inventory/CraftingOverlay.kt
@@ -1,5 +1,6 @@
package moe.nea.firmament.features.inventory
+import io.github.moulberry.repo.data.NEUCraftingRecipe
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
import net.minecraft.item.ItemStack
import net.minecraft.util.Formatting
@@ -7,15 +8,14 @@ import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.ScreenChangeEvent
import moe.nea.firmament.events.SlotRenderEvents
import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.rei.recipes.SBCraftingRecipe
+import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.skyblockId
object CraftingOverlay : FirmamentFeature {
private var screen: GenericContainerScreen? = null
- private var recipe: SBCraftingRecipe? = null
+ private var recipe: NEUCraftingRecipe? = null
private var useNextScreen = false
private val craftingOverlayIndices = listOf(
10, 11, 12,
@@ -24,7 +24,7 @@ object CraftingOverlay : FirmamentFeature {
)
val CRAFTING_SCREEN_NAME = "Craft Item"
- fun setOverlay(screen: GenericContainerScreen?, recipe: SBCraftingRecipe) {
+ fun setOverlay(screen: GenericContainerScreen?, recipe: NEUCraftingRecipe) {
this.screen = screen
if (screen == null) {
useNextScreen = true
@@ -52,10 +52,12 @@ object CraftingOverlay : FirmamentFeature {
if (slot.inventory != screen?.screenHandler?.inventory) return
val recipeIndex = craftingOverlayIndices.indexOf(slot.index)
if (recipeIndex < 0) return
- val expectedItem = recipe.neuRecipe.inputs[recipeIndex]
+ val expectedItem = recipe.inputs[recipeIndex]
val actualStack = slot.stack ?: ItemStack.EMPTY!!
- val actualEntry = SBItemEntryDefinition.getEntry(actualStack).value
- if ((actualEntry.skyblockId.neuItem != expectedItem.itemId || actualEntry.getStackSize() < expectedItem.amount) && expectedItem.amount.toInt() != 0) {
+ val actualEntry = SBItemStack(actualStack)
+ if ((actualEntry.skyblockId != expectedItem.skyblockId || actualEntry.getStackSize() < expectedItem.amount)
+ && expectedItem.amount.toInt() != 0
+ ) {
event.context.fill(
event.slot.x,
event.slot.y,
@@ -65,7 +67,7 @@ object CraftingOverlay : FirmamentFeature {
)
}
if (!slot.hasStack()) {
- val itemStack = SBItemEntryDefinition.getEntry(expectedItem).asItemEntry().value
+ val itemStack = SBItemStack(expectedItem)?.asImmutableItemStack() ?: return
event.context.drawItem(itemStack, event.slot.x, event.slot.y)
event.context.drawItemInSlot(
MC.font,
diff --git a/src/main/kotlin/gui/entity/EntityWidget.kt b/src/main/kotlin/gui/entity/EntityWidget.kt
deleted file mode 100644
index 2e49072..0000000
--- a/src/main/kotlin/gui/entity/EntityWidget.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import me.shedaniel.math.Dimension
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.Element
-import net.minecraft.entity.LivingEntity
-
-class EntityWidget(val entity: LivingEntity, val point: Point) : WidgetWithBounds() {
- override fun children(): List<Element> {
- return emptyList()
- }
-
- var hasErrored = false
-
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- try {
- if (!hasErrored)
- EntityRenderer.renderEntity(entity, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat())
- } catch (ex: Exception) {
- EntityRenderer.logger.error("Failed to render constructed entity: $entity", ex)
- hasErrored = true
- }
- if (hasErrored) {
- context.fill(point.x, point.y, point.x + 50, point.y + 80, 0xFFAA2222.toInt())
- }
- }
-
- override fun getBounds(): Rectangle {
- return Rectangle(point, Dimension(50, 80))
- }
-}
diff --git a/src/main/kotlin/gui/entity/ModifyEquipment.kt b/src/main/kotlin/gui/entity/ModifyEquipment.kt
index 11dfb52..a558936 100644
--- a/src/main/kotlin/gui/entity/ModifyEquipment.kt
+++ b/src/main/kotlin/gui/entity/ModifyEquipment.kt
@@ -1,4 +1,3 @@
-
package moe.nea.firmament.gui.entity
import com.google.gson.JsonObject
@@ -6,50 +5,49 @@ import net.minecraft.component.DataComponentTypes
import net.minecraft.component.type.DyedColorComponent
import net.minecraft.entity.EquipmentSlot
import net.minecraft.entity.LivingEntity
-import net.minecraft.item.ArmorItem
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
-import moe.nea.firmament.rei.SBItemStack
+import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.mc.setEncodedSkullOwner
import moe.nea.firmament.util.mc.zeroUUID
object ModifyEquipment : EntityModifier {
- val names = mapOf(
- "hand" to EquipmentSlot.MAINHAND,
- "helmet" to EquipmentSlot.HEAD,
- "chestplate" to EquipmentSlot.CHEST,
- "leggings" to EquipmentSlot.LEGS,
- "feet" to EquipmentSlot.FEET,
- )
+ val names = mapOf(
+ "hand" to EquipmentSlot.MAINHAND,
+ "helmet" to EquipmentSlot.HEAD,
+ "chestplate" to EquipmentSlot.CHEST,
+ "leggings" to EquipmentSlot.LEGS,
+ "feet" to EquipmentSlot.FEET,
+ )
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- names.forEach { (key, slot) ->
- info[key]?.let {
- entity.equipStack(slot, createItem(it.asString))
- }
- }
- return entity
- }
+ override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
+ names.forEach { (key, slot) ->
+ info[key]?.let {
+ entity.equipStack(slot, createItem(it.asString))
+ }
+ }
+ return entity
+ }
- private fun createItem(item: String): ItemStack {
- val split = item.split("#")
- if (split.size != 2) return SBItemStack(SkyblockId(item)).asImmutableItemStack()
- val (type, data) = split
- return when (type) {
- "SKULL" -> ItemStack(Items.PLAYER_HEAD).also { it.setEncodedSkullOwner(zeroUUID, data) }
- "LEATHER_LEGGINGS" -> coloredLeatherArmor(Items.LEATHER_LEGGINGS, data)
- "LEATHER_BOOTS" -> coloredLeatherArmor(Items.LEATHER_BOOTS, data)
- "LEATHER_HELMET" -> coloredLeatherArmor(Items.LEATHER_HELMET, data)
- "LEATHER_CHESTPLATE" -> coloredLeatherArmor(Items.LEATHER_CHESTPLATE, data)
- else -> error("Unknown leather piece: $type")
- }
- }
+ private fun createItem(item: String): ItemStack {
+ val split = item.split("#")
+ if (split.size != 2) return SBItemStack(SkyblockId(item)).asImmutableItemStack()
+ val (type, data) = split
+ return when (type) {
+ "SKULL" -> ItemStack(Items.PLAYER_HEAD).also { it.setEncodedSkullOwner(zeroUUID, data) }
+ "LEATHER_LEGGINGS" -> coloredLeatherArmor(Items.LEATHER_LEGGINGS, data)
+ "LEATHER_BOOTS" -> coloredLeatherArmor(Items.LEATHER_BOOTS, data)
+ "LEATHER_HELMET" -> coloredLeatherArmor(Items.LEATHER_HELMET, data)
+ "LEATHER_CHESTPLATE" -> coloredLeatherArmor(Items.LEATHER_CHESTPLATE, data)
+ else -> error("Unknown leather piece: $type")
+ }
+ }
- private fun coloredLeatherArmor(leatherArmor: Item, data: String): ItemStack {
- val stack = ItemStack(leatherArmor)
- stack.set(DataComponentTypes.DYED_COLOR, DyedColorComponent(data.toInt(16), false))
- return stack
- }
+ private fun coloredLeatherArmor(leatherArmor: Item, data: String): ItemStack {
+ val stack = ItemStack(leatherArmor)
+ stack.set(DataComponentTypes.DYED_COLOR, DyedColorComponent(data.toInt(16), false))
+ return stack
+ }
}
diff --git a/src/main/kotlin/rei/FirmamentReiPlugin.kt b/src/main/kotlin/rei/FirmamentReiPlugin.kt
deleted file mode 100644
index f234f3e..0000000
--- a/src/main/kotlin/rei/FirmamentReiPlugin.kt
+++ /dev/null
@@ -1,142 +0,0 @@
-package moe.nea.firmament.rei
-
-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
-import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry
-import me.shedaniel.rei.api.client.registry.entry.EntryRegistry
-import me.shedaniel.rei.api.client.registry.screen.ExclusionZones
-import me.shedaniel.rei.api.client.registry.screen.OverlayDecider
-import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
-import me.shedaniel.rei.api.client.registry.transfer.TransferHandler
-import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry
-import me.shedaniel.rei.api.common.entry.EntryStack
-import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
-import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import net.minecraft.item.ItemStack
-import net.minecraft.text.Text
-import net.minecraft.util.ActionResult
-import net.minecraft.util.Identifier
-import moe.nea.firmament.events.HandledScreenPushREIEvent
-import moe.nea.firmament.features.inventory.CraftingOverlay
-import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
-import moe.nea.firmament.rei.recipes.SBCraftingRecipe
-import moe.nea.firmament.rei.recipes.SBEssenceUpgradeRecipe
-import moe.nea.firmament.rei.recipes.SBForgeRecipe
-import moe.nea.firmament.rei.recipes.SBKatRecipe
-import moe.nea.firmament.rei.recipes.SBMobDropRecipe
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.ScreenUtil
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.guessRecipeId
-import moe.nea.firmament.util.skyblockId
-import moe.nea.firmament.util.unformattedString
-
-
-class FirmamentReiPlugin : REIClientPlugin {
-
- companion object {
- fun EntryStack<SBItemStack>.asItemEntry(): EntryStack<ItemStack> {
- return EntryStack.of(VanillaEntryTypes.ITEM, value.asImmutableItemStack())
- }
-
- val SKYBLOCK_ITEM_TYPE_ID = Identifier.of("firmament", "skyblockitems")
- }
-
- override fun registerTransferHandlers(registry: TransferHandlerRegistry) {
- registry.register(TransferHandler { context ->
- val screen = context.containerScreen
- val display = context.display
- if (display !is SBCraftingRecipe) return@TransferHandler TransferHandler.Result.createNotApplicable()
- val neuItem = RepoManager.getNEUItem(SkyblockId(display.neuRecipe.output.itemId))
- ?: error("Could not find neu item ${display.neuRecipe.output.itemId} which is used in a recipe output")
- val useSuperCraft = context.isStackedCrafting || RepoManager.Config.alwaysSuperCraft
- if (neuItem.isVanilla && useSuperCraft) return@TransferHandler TransferHandler.Result.createFailed(Text.translatable(
- "firmament.recipe.novanilla"))
- var shouldReturn = true
- if (context.isActuallyCrafting && !useSuperCraft) {
- if (screen !is GenericContainerScreen || screen.title?.unformattedString != CraftingOverlay.CRAFTING_SCREEN_NAME) {
- MC.sendCommand("craft")
- shouldReturn = false
- }
- CraftingOverlay.setOverlay(screen as? GenericContainerScreen, display)
- }
- if (context.isActuallyCrafting && useSuperCraft) {
- shouldReturn = false
- MC.sendCommand("viewrecipe ${neuItem.guessRecipeId()}")
- }
- return@TransferHandler TransferHandler.Result.createSuccessful().blocksFurtherHandling(shouldReturn)
- })
- }
-
- override fun registerEntryTypes(registry: EntryTypeRegistry) {
- registry.register(SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition)
- }
-
- override fun registerCategories(registry: CategoryRegistry) {
- registry.add(SBCraftingRecipe.Category)
- registry.add(SBForgeRecipe.Category)
- registry.add(SBMobDropRecipe.Category)
- registry.add(SBKatRecipe.Category)
- registry.add(SBEssenceUpgradeRecipe.Category)
- }
-
- override fun registerExclusionZones(zones: ExclusionZones) {
- zones.register(HandledScreen::class.java) { HandledScreenPushREIEvent.publish(HandledScreenPushREIEvent(it)).rectangles }
- zones.register(StorageOverlayScreen::class.java) { it.getBounds() }
- }
-
- override fun registerDisplays(registry: DisplayRegistry) {
- registry.registerDisplayGenerator(
- SBCraftingRecipe.Category.catIdentifier,
- SkyblockCraftingRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
- SBForgeRecipe.Category.categoryIdentifier,
- SkyblockForgeRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
- SBMobDropRecipe.Category.categoryIdentifier,
- SkyblockMobDropRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
- SBKatRecipe.Category.categoryIdentifier,
- SkyblockKatRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
- SBEssenceUpgradeRecipe.Category.categoryIdentifier,
- SkyblockEssenceRecipeDynamicGenerator
- )
- }
-
- override fun registerCollapsibleEntries(registry: CollapsibleEntryRegistry) {
- if (!RepoManager.Config.disableItemGroups)
- RepoManager.neuRepo.constants.parents.parents
- .forEach { (parent, children) ->
- registry.group(
- SkyblockId(parent).identifier,
- Text.literal(RepoManager.getNEUItem(SkyblockId(parent))?.displayName ?: parent),
- (children + parent).map { SBItemEntryDefinition.getEntry(SkyblockId(it)) })
- }
- }
-
- override fun registerScreens(registry: ScreenRegistry) {
- registry.registerDecider(object : OverlayDecider {
- override fun <R : Screen?> isHandingScreen(screen: Class<R>?): Boolean {
- return screen == StorageOverlayScreen::class.java
- }
-
- override fun <R : Screen?> shouldScreenBeOverlaid(screen: R): ActionResult {
- return ActionResult.SUCCESS
- }
- })
- registry.registerFocusedStack(SkyblockItemIdFocusedStackProvider)
- }
-
- override fun registerEntries(registry: EntryRegistry) {
- registry.removeEntryIf { true }
- RepoManager.neuRepo.items?.items?.values?.forEach { neuItem ->
- registry.addEntry(SBItemEntryDefinition.getEntry(neuItem.skyblockId))
- }
- }
-}
diff --git a/src/main/kotlin/rei/NEUItemEntryRenderer.kt b/src/main/kotlin/rei/NEUItemEntryRenderer.kt
deleted file mode 100644
index ba99b30..0000000
--- a/src/main/kotlin/rei/NEUItemEntryRenderer.kt
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2018-2023 shedaniel <daniel@shedaniel.me>
- * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
- * SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
- *
- * SPDX-License-Identifier: GPL-3.0-or-later
- * SPDX-License-Identifier: MIT
- */
-
-package moe.nea.firmament.rei
-
-import com.mojang.blaze3d.platform.GlStateManager.DstFactor
-import com.mojang.blaze3d.platform.GlStateManager.SrcFactor
-import com.mojang.blaze3d.systems.RenderSystem
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.entry.renderer.BatchedEntryRenderer
-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.TooltipContext
-import me.shedaniel.rei.api.common.entry.EntryStack
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.render.DiffuseLighting
-import net.minecraft.client.render.LightmapTextureManager
-import net.minecraft.client.render.OverlayTexture
-import net.minecraft.client.render.VertexConsumerProvider
-import net.minecraft.client.render.model.BakedModel
-import net.minecraft.client.render.model.json.ModelTransformationMode
-import net.minecraft.client.texture.SpriteAtlasTexture
-import net.minecraft.item.Item
-import net.minecraft.item.ItemStack
-import net.minecraft.item.tooltip.TooltipType
-import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
-
-object NEUItemEntryRenderer : EntryRenderer<SBItemStack>, BatchedEntryRenderer<SBItemStack, BakedModel> {
- override fun render(
- entry: EntryStack<SBItemStack>,
- context: DrawContext,
- bounds: Rectangle,
- mouseX: Int,
- mouseY: Int,
- delta: Float
- ) {
- entry.asItemEntry().render(context, bounds, mouseX, mouseY, delta)
- }
-
- val minecraft = MinecraftClient.getInstance()
-
- override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
- val stack = entry.value.asImmutableItemStack()
- val lore = stack.getTooltip(
- Item.TooltipContext.DEFAULT,
- null,
- TooltipType.BASIC
- )
- return Tooltip.create(lore)
- }
-
- override fun getExtraData(entry: EntryStack<SBItemStack>): BakedModel {
- return minecraft.itemRenderer.getModel(entry.asItemEntry().value, minecraft.world, minecraft.player, 0)
- }
-
- override fun getBatchIdentifier(entry: EntryStack<SBItemStack>?, bounds: Rectangle?, extraData: BakedModel): Int {
- return 1738923 + if (extraData.isSideLit) 1 else 0
- }
-
- override fun startBatch(
- entry: EntryStack<SBItemStack>,
- model: BakedModel,
- graphics: DrawContext,
- delta: Float
- ) {
- val modelViewStack = RenderSystem.getModelViewStack()
- modelViewStack.pushMatrix()
- modelViewStack.scale(20.0f, 20.0f, 1.0f)
- RenderSystem.applyModelViewMatrix()
- setupGL(model)
- }
-
- fun setupGL(model: BakedModel) {
- minecraft.textureManager.getTexture(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
- .setFilter(false, false)
- RenderSystem.setShaderTexture(0, SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
- RenderSystem.enableBlend()
- RenderSystem.blendFunc(SrcFactor.SRC_ALPHA, DstFactor.ONE_MINUS_SRC_ALPHA)
- RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f)
- val sideLit = model.isSideLit
- if (!sideLit) {
- DiffuseLighting.disableGuiDepthLighting()
- }
- }
-
- override fun renderBase(
- entry: EntryStack<SBItemStack>,
- model: BakedModel,
- graphics: DrawContext,
- immediate: VertexConsumerProvider.Immediate,
- bounds: Rectangle,
- mouseX: Int,
- mouseY: Int,
- delta: Float
- ) {
- if (entry.isEmpty) return
- val value = entry.asItemEntry().value
- graphics.matrices.push()
- graphics.matrices.translate(bounds.centerX.toFloat() / 20.0f, bounds.centerY.toFloat() / 20.0f, 0.0f)
- graphics.matrices.scale(
- bounds.getWidth().toFloat() / 20.0f,
- -(bounds.getWidth() + bounds.getHeight()).toFloat() / 2.0f / 20.0f,
- 1.0f
- )
- minecraft
- .itemRenderer
- .renderItem(
- value,
- ModelTransformationMode.GUI,
- false,
- graphics.matrices,
- immediate,
- LightmapTextureManager.MAX_LIGHT_COORDINATE,
- OverlayTexture.DEFAULT_UV,
- model
- )
- graphics.matrices.pop()
-
- }
-
- override fun afterBase(
- entry: EntryStack<SBItemStack>,
- model: BakedModel,
- graphics: DrawContext,
- delta: Float
- ) {
- RenderSystem.getModelViewStack().popMatrix()
- RenderSystem.applyModelViewMatrix()
- this.endGL(model)
- }
-
- fun endGL(model: BakedModel) {
- RenderSystem.enableDepthTest()
- val sideLit = model.isSideLit
- if (!sideLit) {
- DiffuseLighting.enableGuiDepthLighting()
- }
- }
-
- override fun renderOverlay(
- entry: EntryStack<SBItemStack>,
- extraData: BakedModel,
- graphics: DrawContext,
- immediate: VertexConsumerProvider.Immediate,
- bounds: Rectangle,
- mouseX: Int,
- mouseY: Int,
- delta: Float
- ) {
- val modelViewStack = RenderSystem.getModelViewStack()
- modelViewStack.pushMatrix()
- modelViewStack.mul(graphics.matrices.peek().positionMatrix)
- modelViewStack.translate(bounds.x.toFloat(), bounds.y.toFloat(), 0.0f)
- modelViewStack.scale(
- bounds.width.toFloat() / 16.0f,
- -(bounds.getWidth() + bounds.getHeight()).toFloat() / 2.0f / 16.0f,
- 1.0f
- )
- RenderSystem.applyModelViewMatrix()
- renderOverlay(DrawContext(minecraft, graphics.vertexConsumers), entry.asItemEntry())
- modelViewStack.popMatrix()
- RenderSystem.applyModelViewMatrix()
- }
-
- fun renderOverlay(graphics: DrawContext, entry: EntryStack<ItemStack>) {
- if (!entry.isEmpty) {
- graphics.drawItemInSlot(MinecraftClient.getInstance().textRenderer, entry.value, 0, 0, null)
- }
- }
-
- override fun endBatch(
- entry: EntryStack<SBItemStack>?,
- extraData: BakedModel?,
- graphics: DrawContext?,
- delta: Float
- ) {
- }
-
-}
diff --git a/src/main/kotlin/rei/NEUItemEntrySerializer.kt b/src/main/kotlin/rei/NEUItemEntrySerializer.kt
deleted file mode 100644
index a35d75f..0000000
--- a/src/main/kotlin/rei/NEUItemEntrySerializer.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-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.util.SkyblockId
-
-object NEUItemEntrySerializer : EntrySerializer<SBItemStack> {
- 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): 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, count)
- }
-
- override fun save(entry: EntryStack<SBItemStack>, value: SBItemStack): NbtCompound {
- return NbtCompound().apply {
- putString(SKYBLOCK_ID_ENTRY, value.skyblockId.neuItem)
- putInt(SKYBLOCK_ITEM_COUNT, value.getStackSize())
- }
- }
-}
diff --git a/src/main/kotlin/rei/SBItemEntryDefinition.kt b/src/main/kotlin/rei/SBItemEntryDefinition.kt
deleted file mode 100644
index 3df8fa3..0000000
--- a/src/main/kotlin/rei/SBItemEntryDefinition.kt
+++ /dev/null
@@ -1,254 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-import io.github.moulberry.repo.constants.PetNumbers
-import io.github.moulberry.repo.data.NEUIngredient
-import io.github.moulberry.repo.data.NEUItem
-import io.github.moulberry.repo.data.Rarity
-import java.util.stream.Stream
-import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer
-import me.shedaniel.rei.api.common.entry.EntrySerializer
-import me.shedaniel.rei.api.common.entry.EntryStack
-import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext
-import me.shedaniel.rei.api.common.entry.type.EntryDefinition
-import me.shedaniel.rei.api.common.entry.type.EntryType
-import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
-import net.minecraft.item.ItemStack
-import net.minecraft.registry.tag.TagKey
-import net.minecraft.text.Text
-import net.minecraft.util.Formatting
-import net.minecraft.util.Identifier
-import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
-import moe.nea.firmament.repo.ExpLadders
-import moe.nea.firmament.repo.ItemCache
-import moe.nea.firmament.repo.ItemCache.asItemStack
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.FirmFormatters
-import moe.nea.firmament.util.HypixelPetInfo
-import moe.nea.firmament.util.LegacyFormattingCode
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.mc.appendLore
-import moe.nea.firmament.util.mc.displayNameAccordingToNbt
-import moe.nea.firmament.util.petData
-import moe.nea.firmament.util.skyBlockId
-import moe.nea.firmament.util.withColor
-
-// TODO: add in extra data like pet info, into this structure
-data class PetData(
- val rarity: Rarity,
- val petId: String,
- val exp: Double,
- val isStub: Boolean = false,
-) {
- companion object {
- fun fromHypixel(petInfo: HypixelPetInfo) = PetData(
- petInfo.tier, petInfo.type, petInfo.exp,
- )
-
- fun forLevel(petId: String, rarity: Rarity, level: Int) = PetData(
- rarity, petId, ExpLadders.getExpLadder(petId, rarity).getPetExpForLevel(level).toDouble()
- )
- }
-
- val levelData by lazy { ExpLadders.getExpLadder(petId, rarity).getPetLevel(exp) }
-}
-
-data class SBItemStack constructor(
- val skyblockId: SkyblockId,
- val neuItem: NEUItem?,
- private var stackSize: Int,
- private var petData: PetData?,
- val extraLore: List<Text> = emptyList(),
- // TODO: grab this star data from nbt if possible
- val stars: Int = 0,
-) {
-
- fun getStackSize() = stackSize
- fun setStackSize(newSize: Int) {
- this.stackSize = newSize
- this.itemStack_ = null
- }
-
- fun getPetData() = petData
- fun setPetData(petData: PetData?) {
- this.petData = petData
- this.itemStack_ = null
- }
-
- constructor(skyblockId: SkyblockId, petData: PetData) : this(
- skyblockId,
- RepoManager.getNEUItem(skyblockId),
- 1,
- petData
- )
-
- constructor(skyblockId: SkyblockId, stackSize: Int = 1) : this(
- skyblockId,
- RepoManager.getNEUItem(skyblockId),
- stackSize,
- RepoManager.getPotentialStubPetData(skyblockId)
- )
-
- private fun injectReplacementDataForPetLevel(
- petInfo: PetNumbers,
- level: Int,
- replacementData: MutableMap<String, String>
- ) {
- val stats = petInfo.interpolatedStatsAtLevel(level) ?: return
- stats.otherNumbers.forEachIndexed { index, it ->
- replacementData[index.toString()] = FirmFormatters.formatCommas(it, 1)
- }
- stats.statNumbers.forEach { (t, u) ->
- replacementData[t] = FirmFormatters.formatCommas(u, 1)
- }
- }
-
- private fun injectReplacementDataForPets(replacementData: MutableMap<String, String>) {
- val petData = this.petData ?: return
- val petInfo = RepoManager.neuRepo.constants.petNumbers[petData.petId]?.get(petData.rarity) ?: return
- if (petData.isStub) {
- val mapLow = mutableMapOf<String, String>()
- injectReplacementDataForPetLevel(petInfo, petInfo.lowLevel, mapLow)
- val mapHigh = mutableMapOf<String, String>()
- injectReplacementDataForPetLevel(petInfo, petInfo.highLevel, mapHigh)
- mapHigh.forEach { (key, highValue) ->
- mapLow.merge(key, highValue) { a, b -> "$a → $b" }
- }
- replacementData.putAll(mapLow)
- replacementData["LVL"] = "${petInfo.lowLevel} → ${petInfo.highLevel}"
- } else {
- injectReplacementDataForPetLevel(petInfo, petData.levelData.currentLevel, replacementData)
- replacementData["LVL"] = petData.levelData.currentLevel.toString()
- }
- }
-
-
- private var itemStack_: ItemStack? = null
-
- private val itemStack: ItemStack
- get() {
- val itemStack = itemStack_ ?: run {
- if (skyblockId == SkyblockId.COINS)
- return@run ItemCache.coinItem(stackSize).also { it.appendLore(extraLore) }
- val replacementData = mutableMapOf<String, String>()
- injectReplacementDataForPets(replacementData)
- return@run neuItem.asItemStack(idHint = skyblockId, replacementData)
- .copyWithCount(stackSize)
- .also { it.appendLore(extraLore) }
- .also { enhanceStatsByStars(it, stars) }
- }
- if (itemStack_ == null)
- itemStack_ = itemStack
- return itemStack
- }
-
-
- private fun starString(stars: Int): Text {
- if (stars <= 0) return Text.empty()
- val tiers = listOf(
- LegacyFormattingCode.GOLD,
- LegacyFormattingCode.LIGHT_PURPLE,
- LegacyFormattingCode.AQUA,
- )
- val maxStars = 5
- if (stars > tiers.size * maxStars) return Text.literal(" ${stars}✪").withColor(Formatting.RED)
- val starBaseTier = (stars - 1) / maxStars
- val starBaseColor = tiers[starBaseTier]
- val starsInCurrentTier = stars - starBaseTier * maxStars
- val starString = Text.literal(" " + "✪".repeat(starsInCurrentTier)).withColor(starBaseColor.modern)
- if (starBaseTier > 0) {
- val starLastTier = tiers[starBaseTier - 1]
- val starsInLastTier = 5 - starsInCurrentTier
- starString.append(Text.literal("✪".repeat(starsInLastTier)).withColor(starLastTier.modern))
- }
- return starString
- }
-
- private fun enhanceStatsByStars(itemStack: ItemStack, stars: Int) {
- if (stars == 0) return
- // TODO: increase stats and add the star level into the nbt data so star displays work
- itemStack.displayNameAccordingToNbt = itemStack.displayNameAccordingToNbt.copy()
- .append(starString(stars))
- }
-
- fun asImmutableItemStack(): ItemStack {
- return itemStack
- }
-
- fun asItemStack(): ItemStack {
- return itemStack.copy()
- }
-}
-
-object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
- override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean {
- return o1.skyblockId == o2.skyblockId && o1.getStackSize() == o2.getStackSize()
- }
-
- override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
- return value.asItemStack()
- }
-
- override fun getValueType(): Class<SBItemStack> = SBItemStack::class.java
- override fun getType(): EntryType<SBItemStack> = EntryType.deferred(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID)
-
- override fun getRenderer(): EntryRenderer<SBItemStack> = NEUItemEntryRenderer
-
- override fun getSerializer(): EntrySerializer<SBItemStack> {
- return NEUItemEntrySerializer
- }
-
- override fun getTagsFor(entry: EntryStack<SBItemStack>?, value: SBItemStack?): Stream<out TagKey<*>>? {
- return Stream.empty()
- }
-
- override fun asFormattedText(entry: EntryStack<SBItemStack>, value: SBItemStack): Text {
- return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asImmutableItemStack())
- }
-
- override fun hash(entry: EntryStack<SBItemStack>, value: SBItemStack, context: ComparisonContext): Long {
- // Repo items are immutable, and get replaced entirely when loaded from disk
- return value.skyblockId.hashCode() * 31L
- }
-
- override fun wildcard(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
- return value.copy(stackSize = 1, petData = RepoManager.getPotentialStubPetData(value.skyblockId),
- stars = 0, extraLore = listOf())
- }
-
- override fun normalize(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
- return wildcard(entry, value)
- }
-
- override fun copy(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
- return value
- }
-
- override fun isEmpty(entry: EntryStack<SBItemStack>?, value: SBItemStack): Boolean {
- return value.getStackSize() == 0
- }
-
- override fun getIdentifier(entry: EntryStack<SBItemStack>?, value: SBItemStack): Identifier {
- return value.skyblockId.identifier
- }
-
- fun getEntry(sbItemStack: SBItemStack): EntryStack<SBItemStack> =
- EntryStack.of(this, sbItemStack)
-
- fun getEntry(skyblockId: SkyblockId, count: Int = 1): EntryStack<SBItemStack> =
- getEntry(SBItemStack(skyblockId, count))
-
- fun getEntry(ingredient: NEUIngredient): EntryStack<SBItemStack> =
- getEntry(SkyblockId(ingredient.itemId), count = ingredient.amount.toInt())
-
- fun getEntry(stack: ItemStack): EntryStack<SBItemStack> =
- getEntry(
- SBItemStack(
- stack.skyBlockId ?: SkyblockId.NULL,
- RepoManager.getNEUItem(stack.skyBlockId ?: SkyblockId.NULL),
- stack.count,
- petData = stack.petData?.let { PetData.fromHypixel(it) }
- )
- )
-}
diff --git a/src/main/kotlin/rei/SkyblockCraftingRecipeDynamicGenerator.kt b/src/main/kotlin/rei/SkyblockCraftingRecipeDynamicGenerator.kt
deleted file mode 100644
index 5136902..0000000
--- a/src/main/kotlin/rei/SkyblockCraftingRecipeDynamicGenerator.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-import io.github.moulberry.repo.data.NEUCraftingRecipe
-import io.github.moulberry.repo.data.NEUForgeRecipe
-import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
-import io.github.moulberry.repo.data.NEUMobDropRecipe
-import io.github.moulberry.repo.data.NEURecipe
-import java.util.Optional
-import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator
-import me.shedaniel.rei.api.client.view.ViewSearchBuilder
-import me.shedaniel.rei.api.common.display.Display
-import me.shedaniel.rei.api.common.entry.EntryStack
-import moe.nea.firmament.rei.recipes.SBCraftingRecipe
-import moe.nea.firmament.rei.recipes.SBEssenceUpgradeRecipe
-import moe.nea.firmament.rei.recipes.SBForgeRecipe
-import moe.nea.firmament.rei.recipes.SBKatRecipe
-import moe.nea.firmament.rei.recipes.SBMobDropRecipe
-import moe.nea.firmament.repo.EssenceRecipeProvider
-import moe.nea.firmament.repo.RepoManager
-
-
-val SkyblockCraftingRecipeDynamicGenerator =
- neuDisplayGenerator<SBCraftingRecipe, NEUCraftingRecipe> { SBCraftingRecipe(it) }
-
-val SkyblockForgeRecipeDynamicGenerator =
- neuDisplayGenerator<SBForgeRecipe, NEUForgeRecipe> { SBForgeRecipe(it) }
-
-val SkyblockMobDropRecipeDynamicGenerator =
- neuDisplayGenerator<SBMobDropRecipe, NEUMobDropRecipe> { SBMobDropRecipe(it) }
-
-val SkyblockKatRecipeDynamicGenerator =
- neuDisplayGenerator<SBKatRecipe, NEUKatUpgradeRecipe> { SBKatRecipe(it) }
-val SkyblockEssenceRecipeDynamicGenerator =
- neuDisplayGenerator<SBEssenceUpgradeRecipe, EssenceRecipeProvider.EssenceUpgradeRecipe> { SBEssenceUpgradeRecipe(it) }
-
-inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(crossinline mapper: (T) -> D) =
- object : DynamicDisplayGenerator<D> {
- override fun getRecipeFor(entry: EntryStack<*>): Optional<List<D>> {
- if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
- val item = entry.castValue<SBItemStack>()
- val recipes = RepoManager.getRecipesFor(item.skyblockId)
- val craftingRecipes = recipes.filterIsInstance<T>()
- return Optional.of(craftingRecipes.map(mapper))
- }
-
- override fun generate(builder: ViewSearchBuilder): Optional<List<D>> {
- if (SBCraftingRecipe.Category.catIdentifier !in builder.categories) return Optional.empty()
- return Optional.of(
- RepoManager.getAllRecipes().filterIsInstance<T>().map { mapper(it) }
- .toList()
- )
- }
-
- override fun getUsageFor(entry: EntryStack<*>): Optional<List<D>> {
- if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
- val item = entry.castValue<SBItemStack>()
- val recipes = RepoManager.getUsagesFor(item.skyblockId)
- val craftingRecipes = recipes.filterIsInstance<T>()
- return Optional.of(craftingRecipes.map(mapper))
-
- }
- }
diff --git a/src/main/kotlin/rei/SkyblockItemIdFocusedStackProvider.kt b/src/main/kotlin/rei/SkyblockItemIdFocusedStackProvider.kt
deleted file mode 100644
index bb0a5a5..0000000
--- a/src/main/kotlin/rei/SkyblockItemIdFocusedStackProvider.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-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 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<EntryStack<*>> {
- if (screen !is HandledScreen<*>) return CompoundEventResult.pass()
- screen as AccessorHandledScreen
- val focusedSlot = screen.focusedSlot_Firmament ?: return CompoundEventResult.pass()
- val item = focusedSlot.stack ?: return CompoundEventResult.pass()
- val skyblockId = item.skyBlockId ?: return CompoundEventResult.pass()
- return CompoundEventResult.interruptTrue(SBItemEntryDefinition.getEntry(skyblockId))
- }
-
- override fun getPriority(): Double = 1_000_000.0
-}
diff --git a/src/main/kotlin/rei/math.kt b/src/main/kotlin/rei/math.kt
deleted file mode 100644
index 1318beb..0000000
--- a/src/main/kotlin/rei/math.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-import me.shedaniel.math.Point
-
-operator fun Point.plus(other: Point): Point = Point(
- this.x + other.x,
- this.y + other.y,
-)
diff --git a/src/main/kotlin/rei/recipes/SBCraftingRecipe.kt b/src/main/kotlin/rei/recipes/SBCraftingRecipe.kt
deleted file mode 100644
index d6bbf0c..0000000
--- a/src/main/kotlin/rei/recipes/SBCraftingRecipe.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUCraftingRecipe
-import io.github.moulberry.repo.data.NEUIngredient
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
-import net.minecraft.block.Blocks
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.rei.SBItemEntryDefinition
-
-class SBCraftingRecipe(override val neuRecipe: NEUCraftingRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier
-
- object Category : DisplayCategory<SBCraftingRecipe> {
- val catIdentifier = CategoryIdentifier.of<SBCraftingRecipe>(Firmament.MOD_ID, "crafing_recipe")
- override fun getCategoryIdentifier(): CategoryIdentifier<out SBCraftingRecipe> = catIdentifier
-
- override fun getTitle(): Text = Text.literal("SkyBlock Crafting")
-
- override fun getIcon(): Renderer = EntryStacks.of(Blocks.CRAFTING_TABLE)
- override fun setupDisplay(display: SBCraftingRecipe, bounds: Rectangle): List<Widget> {
- val point = Point(bounds.centerX - 58, bounds.centerY - 27)
- return buildList {
- add(Widgets.createRecipeBase(bounds))
- add(Widgets.createArrow(Point(point.x + 60, point.y + 18)))
- add(Widgets.createResultSlotBackground(Point(point.x + 95, point.y + 19)))
- for (i in 0 until 3) {
- for (j in 0 until 3) {
- val slot = Widgets.createSlot(Point(point.x + 1 + i * 18, point.y + 1 + j * 18)).markInput()
- add(slot)
- val item = display.neuRecipe.inputs[i + j * 3]
- if (item == NEUIngredient.SENTINEL_EMPTY) continue
- slot.entry(SBItemEntryDefinition.getEntry(item)) // TODO: make use of stackable item entries
- }
- }
- add(
- Widgets.createSlot(Point(point.x + 95, point.y + 19))
- .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.output))
- .disableBackground().markOutput()
- )
- }
- }
-
- }
-
-}
diff --git a/src/main/kotlin/rei/recipes/SBEssenceUpgradeRecipe.kt b/src/main/kotlin/rei/recipes/SBEssenceUpgradeRecipe.kt
deleted file mode 100644
index 80bc2b7..0000000
--- a/src/main/kotlin/rei/recipes/SBEssenceUpgradeRecipe.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-
-package moe.nea.firmament.rei.recipes
-
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.rei.SBItemStack
-import moe.nea.firmament.repo.EssenceRecipeProvider
-import moe.nea.firmament.util.SkyblockId
-
-class SBEssenceUpgradeRecipe(override val neuRecipe: EssenceRecipeProvider.EssenceUpgradeRecipe) : SBRecipe() {
- object Category : DisplayCategory<SBEssenceUpgradeRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBEssenceUpgradeRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "essence_upgrade")
-
- override fun getTitle(): Text {
- return Text.literal("Essence Upgrades")
- }
-
- override fun getIcon(): Renderer {
- return SBItemEntryDefinition.getEntry(SkyblockId("ESSENCE_WITHER"))
- }
-
- override fun setupDisplay(display: SBEssenceUpgradeRecipe, bounds: Rectangle): List<Widget> {
- val recipe = display.neuRecipe
- val list = mutableListOf<Widget>()
- list.add(Widgets.createRecipeBase(bounds))
- list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 - 18 / 2))
- .markInput()
- .entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter - 1))))
- list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 + 18 / 2))
- .markInput()
- .entry(SBItemEntryDefinition.getEntry(recipe.essenceIngredient)))
- list.add(Widgets.createSlot(Point(bounds.maxX - 12 - 16, bounds.centerY - 8))
- .markOutput()
- .entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter))))
- val extraItems = recipe.extraItems
- list.add(Widgets.createArrow(Point(bounds.centerX - 24 / 2,
- if (extraItems.isEmpty()) bounds.centerY - 17 / 2
- else bounds.centerY + 18 / 2)))
- for ((index, item) in extraItems.withIndex()) {
- list.add(Widgets.createSlot(
- Point(bounds.centerX - extraItems.size * 16 / 2 - 2 / 2 + index * 18,
- bounds.centerY - 18 / 2))
- .markInput()
- .entry(SBItemEntryDefinition.getEntry(item)))
- }
- return list
- }
- }
-
- override fun getCategoryIdentifier(): CategoryIdentifier<*> {
- return Category.categoryIdentifier
- }
-}
diff --git a/src/main/kotlin/rei/recipes/SBForgeRecipe.kt b/src/main/kotlin/rei/recipes/SBForgeRecipe.kt
deleted file mode 100644
index 569f4a0..0000000
--- a/src/main/kotlin/rei/recipes/SBForgeRecipe.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUForgeRecipe
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
-import kotlin.math.cos
-import kotlin.math.sin
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.block.Blocks
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.rei.plus
-
-class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
-
- object Category : DisplayCategory<SBForgeRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBForgeRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "forge_recipe")
-
- override fun getTitle(): Text = Text.literal("Forge Recipes")
- override fun getDisplayHeight(): Int {
- return 104
- }
-
- override fun getIcon(): Renderer = EntryStacks.of(Blocks.ANVIL)
- override fun setupDisplay(display: SBForgeRecipe, bounds: Rectangle): List<Widget> {
- return buildList {
- add(Widgets.createRecipeBase(bounds))
- add(Widgets.createResultSlotBackground(Point(bounds.minX + 124, bounds.minY + 46)))
- val arrow = Widgets.createArrow(Point(bounds.minX + 90, bounds.minY + 54 - 18 / 2))
- add(arrow)
- add(Widgets.createTooltip(arrow.bounds, Text.stringifiedTranslatable("firmament.recipe.forge.time", display.neuRecipe.duration.seconds)))
- val ingredientsCenter = Point(bounds.minX + 49 - 8, bounds.minY + 54 - 8)
- val count = display.neuRecipe.inputs.size
- if (count == 1) {
- add(
- Widgets.createSlot(Point(ingredientsCenter.x, ingredientsCenter.y)).markInput()
- .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.inputs.single()))
- )
- } else {
- display.neuRecipe.inputs.forEachIndexed { idx, ingredient ->
- val rad = Math.PI * 2 * idx / count
- add(
- Widgets.createSlot(
- Point(
- cos(rad) * 30,
- sin(rad) * 30,
- ) + ingredientsCenter
- ).markInput().entry(SBItemEntryDefinition.getEntry(ingredient))
- )
- }
- }
- add(
- Widgets.createSlot(Point(bounds.minX + 124, bounds.minY + 46)).markOutput().disableBackground()
- .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.outputStack))
- )
- }
- }
- }
-
-}
diff --git a/src/main/kotlin/rei/recipes/SBKatRecipe.kt b/src/main/kotlin/rei/recipes/SBKatRecipe.kt
deleted file mode 100644
index f906a43..0000000
--- a/src/main/kotlin/rei/recipes/SBKatRecipe.kt
+++ /dev/null
@@ -1,224 +0,0 @@
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
-import io.github.notenoughupdates.moulconfig.common.IMinecraft
-import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-import io.github.notenoughupdates.moulconfig.gui.MouseEvent
-import io.github.notenoughupdates.moulconfig.gui.component.SliderComponent
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import io.github.notenoughupdates.moulconfig.observer.Property
-import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.block.Blocks
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.Element
-import net.minecraft.item.Items
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.rei.PetData
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.rei.SBItemStack
-import moe.nea.firmament.util.FirmFormatters
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SkyblockId
-
-class SBKatRecipe(override val neuRecipe: NEUKatUpgradeRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
-
- object Category : DisplayCategory<SBKatRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBKatRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "kat_recipe")
-
- override fun getTitle(): Text = Text.literal("Kat Pet Upgrade")
- override fun getDisplayHeight(): Int {
- return 100
- }
-
- override fun getIcon(): Renderer = EntryStacks.of(Items.BONE)
- override fun setupDisplay(display: SBKatRecipe, bounds: Rectangle): List<Widget> {
- return buildList {
- val arrowWidth = 24
- val recipe = display.neuRecipe
- val levelValue = Property.upgrade(GetSetter.floating(0F))
- val slider = SliderComponent(levelValue, 1F, 100F, 1f, 100)
- val outputStack = SBItemStack(SkyblockId(recipe.output.itemId))
- val inputStack = SBItemStack(SkyblockId(recipe.input.itemId))
- val inputLevelLabelCenter = Point(bounds.minX + 30 - 18 + 5 + 8, bounds.minY + 25)
- val inputLevelLabel = Widgets.createLabel(
- inputLevelLabelCenter,
- Text.literal("")).centered()
- val outputLevelLabelCenter = Point(bounds.maxX - 30 + 8, bounds.minY + 25)
- val outputLevelLabel = Widgets.createLabel(
- outputLevelLabelCenter,
- Text.literal("")).centered()
- val coinStack = SBItemStack(SkyblockId.COINS, recipe.coins.toInt())
- levelValue.whenChanged { oldValue, newValue ->
- if (oldValue.toInt() == newValue.toInt()) return@whenChanged
- val oldInput = inputStack.getPetData() ?: return@whenChanged
- val newInput = PetData.forLevel(oldInput.petId, oldInput.rarity, newValue.toInt())
- inputStack.setPetData(newInput)
- val oldOutput = outputStack.getPetData() ?: return@whenChanged
- val newOutput = PetData(oldOutput.rarity, oldOutput.petId, newInput.exp)
- outputStack.setPetData(newOutput)
- inputLevelLabel.message = Text.literal(newInput.levelData.currentLevel.toString())
- inputLevelLabel.bounds.location = Point(
- inputLevelLabelCenter.x - MC.font.getWidth(inputLevelLabel.message) / 2,
- inputLevelLabelCenter.y)
- outputLevelLabel.message = Text.literal(newOutput.levelData.currentLevel.toString())
- outputLevelLabel.bounds.location = Point(
- outputLevelLabelCenter.x - MC.font.getWidth(outputLevelLabel.message) / 2,
- outputLevelLabelCenter.y)
- coinStack.setStackSize((recipe.coins * (1 - 0.3 * newValue / 100)).toInt())
- }
- levelValue.set(1F)
- add(Widgets.createRecipeBase(bounds))
- add(wrapWidget(Rectangle(bounds.centerX - slider.width / 2,
- bounds.maxY - 30,
- slider.width,
- slider.height),
- slider))
- add(Widgets.withTooltip(
- Widgets.createArrow(Point(bounds.centerX - arrowWidth / 2, bounds.minY + 40)),
- Text.literal("Upgrade time: " + FirmFormatters.formatTimespan(recipe.seconds.seconds))))
-
- add(Widgets.createResultSlotBackground(Point(bounds.maxX - 30, bounds.minY + 40)))
- add(inputLevelLabel)
- add(outputLevelLabel)
- add(Widgets.createSlot(Point(bounds.maxX - 30, bounds.minY + 40)).markOutput().disableBackground()
- .entry(SBItemEntryDefinition.getEntry(outputStack)))
- add(Widgets.createSlot(Point(bounds.minX + 30 - 18 + 5, bounds.minY + 40)).markInput()
- .entry(SBItemEntryDefinition.getEntry(inputStack)))
-
- val allInputs = recipe.items.map { SBItemEntryDefinition.getEntry(it) } +
- listOf(SBItemEntryDefinition.getEntry(coinStack))
- for ((index, item) in allInputs.withIndex()) {
- add(Widgets.createSlot(
- Point(bounds.centerX + index * 20 - allInputs.size * 18 / 2 - (allInputs.size - 1) * 2 / 2,
- bounds.minY + 20))
- .markInput()
- .entry(item))
- }
- }
- }
- }
-}
-
-fun wrapWidget(bounds: Rectangle, component: GuiComponent): Widget {
- return object : WidgetWithBounds() {
- override fun getBounds(): Rectangle {
- return bounds
- }
-
- override fun children(): List<Element> {
- return listOf()
- }
-
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- context.matrices.push()
- context.matrices.translate(bounds.minX.toFloat(), bounds.minY.toFloat(), 0F)
- component.render(
- GuiImmediateContext(
- ModernRenderContext(context),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseX - bounds.minX, mouseY - bounds.minY,
- mouseX, mouseY,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- context.matrices.pop()
- }
-
- override fun mouseMoved(mouseX: Double, mouseY: Double) {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- component.mouseEvent(MouseEvent.Move(0F, 0F),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- }
-
- override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Click(button, true),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- }
-
- override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Click(button, false),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- }
-
- override fun mouseDragged(
- mouseX: Double,
- mouseY: Double,
- button: Int,
- deltaX: Double,
- deltaY: Double
- ): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Move(deltaX.toFloat(), deltaY.toFloat()),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
-
- }
-
- override fun mouseScrolled(
- mouseX: Double,
- mouseY: Double,
- horizontalAmount: Double,
- verticalAmount: Double
- ): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Scroll(verticalAmount.toFloat()),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- }
- }
-}
diff --git a/src/main/kotlin/rei/recipes/SBMobDropRecipe.kt b/src/main/kotlin/rei/recipes/SBMobDropRecipe.kt
deleted file mode 100644
index a02220f..0000000
--- a/src/main/kotlin/rei/recipes/SBMobDropRecipe.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUMobDropRecipe
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
-import net.minecraft.item.Items
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.gui.entity.EntityRenderer
-import moe.nea.firmament.gui.entity.EntityWidget
-import moe.nea.firmament.rei.SBItemEntryDefinition
-
-class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
-
- object Category : DisplayCategory<SBMobDropRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBMobDropRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "mob_drop_recipe")
-
- override fun getTitle(): Text = Text.literal("Mob Drops")
- override fun getDisplayHeight(): Int {
- return 100
- }
-
- override fun getIcon(): Renderer = EntryStacks.of(Items.DIAMOND_SWORD)
- override fun setupDisplay(display: SBMobDropRecipe, bounds: Rectangle): List<Widget> {
- return buildList {
- add(Widgets.createRecipeBase(bounds))
- val source = display.neuRecipe.render
- val entity = if (source.startsWith("@")) {
- EntityRenderer.constructEntity(Identifier.of(source.substring(1)))
- } else {
- EntityRenderer.applyModifiers(source, listOf())
- }
- if (entity != null) {
- val level = display.neuRecipe.level
- val fullMobName =
- if (level > 0) Text.translatable("firmament.recipe.mobs.name", level, display.neuRecipe.name)
- else Text.translatable("firmament.recipe.mobs.name.nolevel", display.neuRecipe.name)
- val tt = mutableListOf<Text>()
- tt.add((fullMobName))
- tt.add(Text.literal(""))
- if (display.neuRecipe.coins > 0) {
- tt.add(Text.stringifiedTranslatable("firmament.recipe.mobs.coins", display.neuRecipe.coins))
- }
- if (display.neuRecipe.combatExperience > 0) {
- tt.add(
- Text.stringifiedTranslatable(
- "firmament.recipe.mobs.combat",
- display.neuRecipe.combatExperience
- )
- )
- }
- if (display.neuRecipe.enchantingExperience > 0) {
- tt.add(
- Text.stringifiedTranslatable(
- "firmament.recipe.mobs.exp",
- display.neuRecipe.enchantingExperience
- )
- )
- }
- if (display.neuRecipe.extra != null)
- display.neuRecipe.extra.mapTo(tt) { Text.literal(it) }
- if (tt.size == 2)
- tt.removeAt(1)
- add(
- Widgets.withTooltip(
- EntityWidget(entity, Point(bounds.minX + 5, bounds.minY + 15)),
- tt
- )
- )
- }
- add(
- Widgets.createLabel(Point(bounds.minX + 15, bounds.minY + 5), Text.literal(display.neuRecipe.name))
- .leftAligned()
- )
- var x = bounds.minX + 60
- var y = bounds.minY + 20
- for (drop in display.neuRecipe.drops) {
- val lore = drop.extra.mapTo(mutableListOf()) { Text.literal(it) }
- if (drop.chance != null) {
- lore += listOf(Text.translatable("firmament.recipe.mobs.drops", drop.chance))
- }
- val item = SBItemEntryDefinition.getEntry(drop.dropItem)
- .value.copy(extraLore = lore)
- add(
- Widgets.createSlot(Point(x, y)).markOutput()
- .entries(listOf(SBItemEntryDefinition.getEntry(item)))
- )
- x += 18
- if (x > bounds.maxX - 30) {
- x = bounds.minX + 60
- y += 18
- }
- }
- }
- }
- }
-
-}
diff --git a/src/main/kotlin/rei/recipes/SBRecipe.kt b/src/main/kotlin/rei/recipes/SBRecipe.kt
deleted file mode 100644
index 7872d83..0000000
--- a/src/main/kotlin/rei/recipes/SBRecipe.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUIngredient
-import io.github.moulberry.repo.data.NEURecipe
-import me.shedaniel.rei.api.common.display.Display
-import me.shedaniel.rei.api.common.entry.EntryIngredient
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.util.SkyblockId
-
-abstract class SBRecipe : Display {
- abstract val neuRecipe: NEURecipe
- override fun getInputEntries(): List<EntryIngredient> {
- return neuRecipe.allInputs
- .filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
- .map {
- val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
- EntryIngredient.of(entryStack)
- }
- }
-
- override fun getOutputEntries(): List<EntryIngredient> {
- return neuRecipe.allOutputs
- .filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
- .map {
- val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
- EntryIngredient.of(entryStack)
- }
- }
-}
diff --git a/src/main/kotlin/repo/PetData.kt b/src/main/kotlin/repo/PetData.kt
new file mode 100644
index 0000000..2ce3402
--- /dev/null
+++ b/src/main/kotlin/repo/PetData.kt
@@ -0,0 +1,24 @@
+package moe.nea.firmament.repo
+
+import io.github.moulberry.repo.data.Rarity
+import moe.nea.firmament.util.HypixelPetInfo
+
+// TODO: add in extra data like pet info, into this structure
+data class PetData(
+ val rarity: Rarity,
+ val petId: String,
+ val exp: Double,
+ val isStub: Boolean = false,
+) {
+ companion object {
+ fun fromHypixel(petInfo: HypixelPetInfo) = PetData(
+ petInfo.tier, petInfo.type, petInfo.exp,
+ )
+
+ fun forLevel(petId: String, rarity: Rarity, level: Int) = PetData(
+ rarity, petId, ExpLadders.getExpLadder(petId, rarity).getPetExpForLevel(level).toDouble()
+ )
+ }
+
+ val levelData by lazy { ExpLadders.getExpLadder(petId, rarity).getPetLevel(exp) }
+}
diff --git a/src/main/kotlin/repo/RepoManager.kt b/src/main/kotlin/repo/RepoManager.kt
index ab0d9cf..b586548 100644
--- a/src/main/kotlin/repo/RepoManager.kt
+++ b/src/main/kotlin/repo/RepoManager.kt
@@ -14,7 +14,6 @@ import moe.nea.firmament.Firmament
import moe.nea.firmament.Firmament.logger
import moe.nea.firmament.events.ReloadRegistrationEvent
import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.rei.PetData
import moe.nea.firmament.util.MinecraftDispatcher
import moe.nea.firmament.util.SkyblockId
@@ -139,9 +138,9 @@ object RepoManager {
return null
}
val intIndex = rarityIndex.toInt()
- if (intIndex !in Rarity.values().indices) return null
+ if (intIndex !in Rarity.entries.indices) return null
if (petId !in neuRepo.constants.petNumbers) return null
- return PetData(Rarity.values()[intIndex], petId, 0.0, true)
+ return PetData(Rarity.entries[intIndex], petId, 0.0, true)
}
}
diff --git a/src/main/kotlin/repo/SBItemStack.kt b/src/main/kotlin/repo/SBItemStack.kt
new file mode 100644
index 0000000..281075d
--- /dev/null
+++ b/src/main/kotlin/repo/SBItemStack.kt
@@ -0,0 +1,165 @@
+package moe.nea.firmament.repo
+
+import io.github.moulberry.repo.constants.PetNumbers
+import io.github.moulberry.repo.data.NEUIngredient
+import io.github.moulberry.repo.data.NEUItem
+import net.minecraft.item.ItemStack
+import net.minecraft.text.Text
+import net.minecraft.util.Formatting
+import moe.nea.firmament.repo.ItemCache.asItemStack
+import moe.nea.firmament.util.FirmFormatters
+import moe.nea.firmament.util.LegacyFormattingCode
+import moe.nea.firmament.util.SkyblockId
+import moe.nea.firmament.util.mc.appendLore
+import moe.nea.firmament.util.mc.displayNameAccordingToNbt
+import moe.nea.firmament.util.petData
+import moe.nea.firmament.util.skyBlockId
+import moe.nea.firmament.util.skyblockId
+import moe.nea.firmament.util.withColor
+
+data class SBItemStack constructor(
+ val skyblockId: SkyblockId,
+ val neuItem: NEUItem?,
+ private var stackSize: Int,
+ private var petData: PetData?,
+ val extraLore: List<Text> = emptyList(),
+ // TODO: grab this star data from nbt if possible
+ val stars: Int = 0,
+) {
+
+ fun getStackSize() = stackSize
+ fun setStackSize(newSize: Int) {
+ this.stackSize = newSize
+ this.itemStack_ = null
+ }
+
+ fun getPetData() = petData
+ fun setPetData(petData: PetData?) {
+ this.petData = petData
+ this.itemStack_ = null
+ }
+
+ companion object {
+ operator fun invoke(itemStack: ItemStack): SBItemStack {
+ val skyblockId = itemStack.skyBlockId ?: SkyblockId.NULL
+ return SBItemStack(
+ skyblockId,
+ RepoManager.getNEUItem(skyblockId),
+ itemStack.count,
+ petData = itemStack.petData?.let { PetData.fromHypixel(it) }
+ )
+ }
+
+ operator fun invoke(neuIngredient: NEUIngredient): SBItemStack? {
+ if (neuIngredient.skyblockId == SkyblockId.SENTINEL_EMPTY) return null // TODO: better fallback, maybe?
+ if (neuIngredient.skyblockId == SkyblockId.COINS) {
+ // TODO: specially handle coins to include the decimals
+ }
+ return SBItemStack(neuIngredient.skyblockId, neuIngredient.amount.toInt())
+ }
+ }
+
+ constructor(skyblockId: SkyblockId, petData: PetData) : this(
+ skyblockId,
+ RepoManager.getNEUItem(skyblockId),
+ 1,
+ petData
+ )
+
+ constructor(skyblockId: SkyblockId, stackSize: Int = 1) : this(
+ skyblockId,
+ RepoManager.getNEUItem(skyblockId),
+ stackSize,
+ RepoManager.getPotentialStubPetData(skyblockId)
+ )
+
+ private fun injectReplacementDataForPetLevel(
+ petInfo: PetNumbers,
+ level: Int,
+ replacementData: MutableMap<String, String>
+ ) {
+ val stats = petInfo.interpolatedStatsAtLevel(level) ?: return
+ stats.otherNumbers.forEachIndexed { index, it ->
+ replacementData[index.toString()] = FirmFormatters.formatCommas(it, 1)
+ }
+ stats.statNumbers.forEach { (t, u) ->
+ replacementData[t] = FirmFormatters.formatCommas(u, 1)
+ }
+ }
+
+ private fun injectReplacementDataForPets(replacementData: MutableMap<String, String>) {
+ val petData = this.petData ?: return
+ val petInfo = RepoManager.neuRepo.constants.petNumbers[petData.petId]?.get(petData.rarity) ?: return
+ if (petData.isStub) {
+ val mapLow = mutableMapOf<String, String>()
+ injectReplacementDataForPetLevel(petInfo, petInfo.lowLevel, mapLow)
+ val mapHigh = mutableMapOf<String, String>()
+ injectReplacementDataForPetLevel(petInfo, petInfo.highLevel, mapHigh)
+ mapHigh.forEach { (key, highValue) ->
+ mapLow.merge(key, highValue) { a, b -> "$a → $b" }
+ }
+ replacementData.putAll(mapLow)
+ replacementData["LVL"] = "${petInfo.lowLevel} → ${petInfo.highLevel}"
+ } else {
+ injectReplacementDataForPetLevel(petInfo, petData.levelData.currentLevel, replacementData)
+ replacementData["LVL"] = petData.levelData.currentLevel.toString()
+ }
+ }
+
+
+ private var itemStack_: ItemStack? = null
+
+ private val itemStack: ItemStack
+ get() {
+ val itemStack = itemStack_ ?: run {
+ if (skyblockId == SkyblockId.COINS)
+ return@run ItemCache.coinItem(stackSize).also { it.appendLore(extraLore) }
+ val replacementData = mutableMapOf<String, String>()
+ injectReplacementDataForPets(replacementData)
+ return@run neuItem.asItemStack(idHint = skyblockId, replacementData)
+ .copyWithCount(stackSize)
+ .also { it.appendLore(extraLore) }
+ .also { enhanceStatsByStars(it, stars) }
+ }
+ if (itemStack_ == null)
+ itemStack_ = itemStack
+ return itemStack
+ }
+
+
+ private fun starString(stars: Int): Text {
+ if (stars <= 0) return Text.empty()
+ val tiers = listOf(
+ LegacyFormattingCode.GOLD,
+ LegacyFormattingCode.LIGHT_PURPLE,
+ LegacyFormattingCode.AQUA,
+ )
+ val maxStars = 5
+ if (stars > tiers.size * maxStars) return Text.literal(" ${stars}✪").withColor(Formatting.RED)
+ val starBaseTier = (stars - 1) / maxStars
+ val starBaseColor = tiers[starBaseTier]
+ val starsInCurrentTier = stars - starBaseTier * maxStars
+ val starString = Text.literal(" " + "✪".repeat(starsInCurrentTier)).withColor(starBaseColor.modern)
+ if (starBaseTier > 0) {
+ val starLastTier = tiers[starBaseTier - 1]
+ val starsInLastTier = 5 - starsInCurrentTier
+ starString.append(Text.literal("✪".repeat(starsInLastTier)).withColor(starLastTier.modern))
+ }
+ return starString
+ }
+
+ private fun enhanceStatsByStars(itemStack: ItemStack, stars: Int) {
+ if (stars == 0) return
+ // TODO: increase stats and add the star level into the nbt data so star displays work
+ itemStack.displayNameAccordingToNbt = itemStack.displayNameAccordingToNbt.copy()
+ .append(starString(stars))
+ }
+
+ fun asImmutableItemStack(): ItemStack {
+ return itemStack
+ }
+
+ fun asCopiedItemStack(): ItemStack {
+ return itemStack.copy()
+ }
+}
diff --git a/src/main/kotlin/util/HoveredItemStack.kt b/src/main/kotlin/util/HoveredItemStack.kt
index 47a59d0..a2e4ad2 100644
--- a/src/main/kotlin/util/HoveredItemStack.kt
+++ b/src/main/kotlin/util/HoveredItemStack.kt
@@ -1,31 +1,27 @@
-
-
package moe.nea.firmament.util
-import me.shedaniel.math.impl.PointHelper
-import me.shedaniel.rei.api.client.REIRuntime
-import me.shedaniel.rei.api.client.gui.widgets.Slot
-import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
-import net.minecraft.client.gui.Element
-import net.minecraft.client.gui.ParentElement
+import com.google.auto.service.AutoService
import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.item.ItemStack
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
+import moe.nea.firmament.util.compatloader.CompatLoader
+
+interface HoveredItemStackProvider {
+ fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack?
+
+ companion object : CompatLoader<HoveredItemStackProvider>(HoveredItemStackProvider::class)
+}
+@AutoService(HoveredItemStackProvider::class)
+class VanillaScreenProvider : HoveredItemStackProvider {
+ override fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack? {
+ screen as AccessorHandledScreen
+ val vanillaSlot = screen.focusedSlot_Firmament?.stack
+ return vanillaSlot
+ }
+}
val HandledScreen<*>.focusedItemStack: ItemStack?
- get() {
- this as AccessorHandledScreen
- val vanillaSlot = this.focusedSlot_Firmament?.stack
- if (vanillaSlot != null) return vanillaSlot
- val focusedSlot = ScreenRegistry.getInstance().getFocusedStack(this, PointHelper.ofMouse())
- if (focusedSlot != null) return focusedSlot.cheatsAs().value
- var baseElement: Element? = REIRuntime.getInstance().overlay.orElse(null)
- val mx = PointHelper.getMouseFloatingX()
- val my = PointHelper.getMouseFloatingY()
- while (true) {
- if (baseElement is Slot) return baseElement.currentEntry.cheatsAs().value
- if (baseElement !is ParentElement) return null
- baseElement = baseElement.hoveredElement(mx, my).orElse(null)
- }
- }
+ get() =
+ HoveredItemStackProvider.allValidInstances
+ .firstNotNullOfOrNull { it.provideHoveredItemStack(this) }
diff --git a/src/main/kotlin/util/SkyblockId.kt b/src/main/kotlin/util/SkyblockId.kt
index 31227e2..059e746 100644
--- a/src/main/kotlin/util/SkyblockId.kt
+++ b/src/main/kotlin/util/SkyblockId.kt
@@ -2,6 +2,7 @@
package moe.nea.firmament.util
+import io.github.moulberry.repo.data.NEUIngredient
import io.github.moulberry.repo.data.NEUItem
import io.github.moulberry.repo.data.Rarity
import java.util.Optional
@@ -61,7 +62,8 @@ value class SkyblockId(val neuItem: String) {
}
companion object {
- val COINS: SkyblockId = SkyblockId("SKYBLOCK_COIN")
+ val COINS: SkyblockId = SkyblockId(NEUIngredient.NEU_SENTINEL_COINS)
+ val SENTINEL_EMPTY: SkyblockId = SkyblockId(NEUIngredient.NEU_SENTINEL_EMPTY)
private val bazaarEnchantmentRegex = "ENCHANTMENT_(\\D*)_(\\d+)".toRegex()
val NULL: SkyblockId = SkyblockId("null")
val PET_NULL: SkyblockId = SkyblockId("null_pet")
@@ -70,6 +72,7 @@ value class SkyblockId(val neuItem: String) {
}
val NEUItem.skyblockId get() = SkyblockId(skyblockItemId)
+val NEUIngredient.skyblockId get() = SkyblockId(itemId)
fun NEUItem.guessRecipeId(): String? {
if (!skyblockItemId.contains(";")) return skyblockItemId
diff --git a/src/main/kotlin/util/compatloader/CompatLoader.kt b/src/main/kotlin/util/compatloader/CompatLoader.kt
index c5d45bc..6b60e87 100644
--- a/src/main/kotlin/util/compatloader/CompatLoader.kt
+++ b/src/main/kotlin/util/compatloader/CompatLoader.kt
@@ -2,10 +2,13 @@ package moe.nea.firmament.util.compatloader
import java.util.ServiceLoader
import net.fabricmc.loader.api.FabricLoader
+import kotlin.reflect.KClass
import kotlin.streams.asSequence
import moe.nea.firmament.Firmament
abstract class CompatLoader<T : Any>(val kClass: Class<T>) {
+ constructor(kClass: KClass<T>) : this(kClass.java)
+
val loader: ServiceLoader<T> = ServiceLoader.load(kClass)
val allValidInstances by lazy {
loader.reload()