Make REI optional

This commit is contained in:
Linnea Gräf
2024-10-28 12:07:55 +01:00
parent 8ab4408854
commit c38dcee2c5
28 changed files with 451 additions and 374 deletions

View File

@@ -185,6 +185,7 @@ val yaclSourceSet = createIsolatedSourceSet("yacl")
val explosiveEnhancementSourceSet = createIsolatedSourceSet("explosiveEnhancement")
val wildfireGenderSourceSet = createIsolatedSourceSet("wildfireGender")
val modmenuSourceSet = createIsolatedSourceSet("modmenu")
val reiSourceSet = createIsolatedSourceSet("rei")
dependencies {
// Minecraft dependencies
@@ -199,6 +200,8 @@ dependencies {
modImplementation(libs.fabric.kotlin)
modImplementation(libs.moulconfig)
modImplementation(libs.manninghamMills)
modImplementation(libs.basicMath)
include(libs.basicMath)
(modmenuSourceSet.modImplementationConfigurationName)(libs.modmenu)
(explosiveEnhancementSourceSet.modImplementationConfigurationName)(libs.explosiveenhancement)
modImplementation(libs.hypixelmodapi)
@@ -234,13 +237,14 @@ dependencies {
(yaclSourceSet.modImplementationConfigurationName)(libs.yacl)
// Actual dependencies
modCompileOnly(libs.rei.api) {
(reiSourceSet.modImplementationConfigurationName)(libs.rei.api) {
exclude(module = "architectury")
exclude(module = "architectury-fabric")
}
nonModImplentation(libs.repoparser)
shadowMe(libs.repoparser)
fun ktor(mod: String) = "io.ktor:ktor-$mod-jvm:${libs.versions.ktor.get()}"
// TODO: get rid of ktor. lowkey ballooning file size and like not neccessary at all for what i am doing.0
transInclude(nonModImplentation(ktor("client-core"))!!)
transInclude(nonModImplentation(ktor("client-java"))!!)
transInclude(nonModImplentation(ktor("serialization-kotlinx-json"))!!)

View File

@@ -79,6 +79,9 @@ manninghamMills = "2.4.1"
# Update from https://docs.isxander.dev/yet-another-config-lib/installing-yacl
yacl = "3.5.0+1.21-fabric"
# Update from https://maven.shedaniel.me/me/shedaniel/cloth/basic-math/0.6.1/
basicMath = "0.6.1"
[libraries]
minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" }
fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" }
@@ -113,6 +116,7 @@ freecammod = { module = "maven.modrinth:freecam", version.ref = "freecammod" }
citresewn = { module = "maven.modrinth:cit-resewn", version.ref = "citresewn" }
femalegender = { module = "maven.modrinth:female-gender", version.ref = "femalegender" }
yacl = { module = "dev.isxander:yet-another-config-lib", version.ref = "yacl" }
basicMath = { module = "me.shedaniel.cloth:basic-math", version.ref = "basicMath" }
[bundles]
runtime_required = [

View File

@@ -1,10 +1,10 @@
package moe.nea.firmament.gui.entity
package moe.nea.firmament.compat.rei
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 moe.nea.firmament.gui.entity.EntityRenderer
import net.minecraft.client.gui.DrawContext
import net.minecraft.client.gui.Element
import net.minecraft.entity.LivingEntity

View File

@@ -1,4 +1,4 @@
package moe.nea.firmament.rei
package moe.nea.firmament.compat.rei
import me.shedaniel.rei.api.client.plugins.REIClientPlugin
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry
@@ -23,12 +23,13 @@ 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.compat.rei.recipes.SBCraftingRecipe
import moe.nea.firmament.compat.rei.recipes.SBEssenceUpgradeRecipe
import moe.nea.firmament.compat.rei.recipes.SBForgeRecipe
import moe.nea.firmament.compat.rei.recipes.SBKatRecipe
import moe.nea.firmament.compat.rei.recipes.SBMobDropRecipe
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.ScreenUtil
import moe.nea.firmament.util.SkyblockId
@@ -63,7 +64,7 @@ class FirmamentReiPlugin : REIClientPlugin {
MC.sendCommand("craft")
shouldReturn = false
}
CraftingOverlay.setOverlay(screen as? GenericContainerScreen, display)
CraftingOverlay.setOverlay(screen as? GenericContainerScreen, display.neuRecipe)
}
if (context.isActuallyCrafting && useSuperCraft) {
shouldReturn = false

View File

@@ -0,0 +1,37 @@
package moe.nea.firmament.compat.rei
import com.google.auto.service.AutoService
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 net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.item.ItemStack
import moe.nea.firmament.util.HoveredItemStackProvider
import moe.nea.firmament.util.compatloader.CompatLoader
@AutoService(HoveredItemStackProvider::class)
@CompatLoader.RequireMod("roughlyenoughitems")
class ScreenRegistryHoveredItemStackProvider : HoveredItemStackProvider {
override fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack? {
val entryStack = ScreenRegistry.getInstance().getFocusedStack(screen, PointHelper.ofMouse())
?: return null
return entryStack.value as? ItemStack ?: entryStack.cheatsAs().value
}
}
@AutoService(HoveredItemStackProvider::class)
@CompatLoader.RequireMod("roughlyenoughitems")
class OverlayHoveredItemStackProvider : HoveredItemStackProvider {
override fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack? {
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)
}
}
}

View File

@@ -7,7 +7,7 @@
* SPDX-License-Identifier: MIT
*/
package moe.nea.firmament.rei
package moe.nea.firmament.compat.rei
import com.mojang.blaze3d.platform.GlStateManager.DstFactor
import com.mojang.blaze3d.platform.GlStateManager.SrcFactor
@@ -30,7 +30,8 @@ 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
import moe.nea.firmament.compat.rei.FirmamentReiPlugin.Companion.asItemEntry
import moe.nea.firmament.repo.SBItemStack
object NEUItemEntryRenderer : EntryRenderer<SBItemStack>, BatchedEntryRenderer<SBItemStack, BakedModel> {
override fun render(

View File

@@ -1,10 +1,11 @@
package moe.nea.firmament.rei
package moe.nea.firmament.compat.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.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId
object NEUItemEntrySerializer : EntrySerializer<SBItemStack> {

View File

@@ -0,0 +1,94 @@
package moe.nea.firmament.compat.rei
import io.github.moulberry.repo.data.NEUIngredient
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.Identifier
import moe.nea.firmament.compat.rei.FirmamentReiPlugin.Companion.asItemEntry
import moe.nea.firmament.repo.PetData
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.petData
import moe.nea.firmament.util.skyBlockId
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.asCopiedItemStack()
}
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) }
)
)
}

View File

@@ -1,6 +1,6 @@
package moe.nea.firmament.rei
package moe.nea.firmament.compat.rei
import io.github.moulberry.repo.data.NEUCraftingRecipe
import io.github.moulberry.repo.data.NEUForgeRecipe
@@ -12,13 +12,14 @@ 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.compat.rei.recipes.SBCraftingRecipe
import moe.nea.firmament.compat.rei.recipes.SBEssenceUpgradeRecipe
import moe.nea.firmament.compat.rei.recipes.SBForgeRecipe
import moe.nea.firmament.compat.rei.recipes.SBKatRecipe
import moe.nea.firmament.compat.rei.recipes.SBMobDropRecipe
import moe.nea.firmament.repo.EssenceRecipeProvider
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
val SkyblockCraftingRecipeDynamicGenerator =

View File

@@ -1,6 +1,6 @@
package moe.nea.firmament.rei
package moe.nea.firmament.compat.rei
import dev.architectury.event.CompoundEventResult
import me.shedaniel.math.Point

View File

@@ -1,6 +1,6 @@
package moe.nea.firmament.rei
package moe.nea.firmament.compat.rei
import me.shedaniel.math.Point

View File

@@ -1,6 +1,6 @@
package moe.nea.firmament.rei.recipes
package moe.nea.firmament.compat.rei.recipes
import io.github.moulberry.repo.data.NEUCraftingRecipe
import io.github.moulberry.repo.data.NEUIngredient
@@ -15,7 +15,7 @@ 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
import moe.nea.firmament.compat.rei.SBItemEntryDefinition
class SBCraftingRecipe(override val neuRecipe: NEUCraftingRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier

View File

@@ -1,5 +1,5 @@
package moe.nea.firmament.rei.recipes
package moe.nea.firmament.compat.rei.recipes
import me.shedaniel.math.Point
import me.shedaniel.math.Rectangle
@@ -10,9 +10,9 @@ 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.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.repo.EssenceRecipeProvider
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId
class SBEssenceUpgradeRecipe(override val neuRecipe: EssenceRecipeProvider.EssenceUpgradeRecipe) : SBRecipe() {

View File

@@ -1,6 +1,6 @@
package moe.nea.firmament.rei.recipes
package moe.nea.firmament.compat.rei.recipes
import io.github.moulberry.repo.data.NEUForgeRecipe
import me.shedaniel.math.Point
@@ -17,8 +17,8 @@ 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
import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.compat.rei.plus
class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier

View File

@@ -1,5 +1,5 @@
package moe.nea.firmament.rei.recipes
package moe.nea.firmament.compat.rei.recipes
import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
import io.github.notenoughupdates.moulconfig.common.IMinecraft
@@ -26,9 +26,9 @@ 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.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.repo.PetData
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.FirmFormatters
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SkyblockId

View File

@@ -1,5 +1,5 @@
package moe.nea.firmament.rei.recipes
package moe.nea.firmament.compat.rei.recipes
import io.github.moulberry.repo.data.NEUMobDropRecipe
import me.shedaniel.math.Point
@@ -15,8 +15,8 @@ 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
import moe.nea.firmament.compat.rei.EntityWidget
import moe.nea.firmament.compat.rei.SBItemEntryDefinition
class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier

View File

@@ -1,12 +1,10 @@
package moe.nea.firmament.rei.recipes
package moe.nea.firmament.compat.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.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.util.SkyblockId
abstract class SBRecipe : Display {

View File

@@ -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
}
}

View File

@@ -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,

View File

@@ -1,4 +1,3 @@
package moe.nea.firmament.gui.entity
import com.google.gson.JsonObject
@@ -6,11 +5,10 @@ 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

View File

@@ -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) }
)
)
}

View File

@@ -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) }
}

View File

@@ -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)
}
}

View File

@@ -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()
}
}

View File

@@ -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) }

View File

@@ -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

View File

@@ -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()

View File

@@ -31,7 +31,7 @@
"moe.nea.firmament.Firmament::onClientInitialize"
],
"rei_client": [
"moe.nea.firmament.rei.FirmamentReiPlugin"
"moe.nea.firmament.compat.rei.FirmamentReiPlugin"
],
"modmenu": [
"moe.nea.firmament.compat.modmenu.FirmamentModMenuPlugin"