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 explosiveEnhancementSourceSet = createIsolatedSourceSet("explosiveEnhancement")
val wildfireGenderSourceSet = createIsolatedSourceSet("wildfireGender") val wildfireGenderSourceSet = createIsolatedSourceSet("wildfireGender")
val modmenuSourceSet = createIsolatedSourceSet("modmenu") val modmenuSourceSet = createIsolatedSourceSet("modmenu")
val reiSourceSet = createIsolatedSourceSet("rei")
dependencies { dependencies {
// Minecraft dependencies // Minecraft dependencies
@@ -199,6 +200,8 @@ dependencies {
modImplementation(libs.fabric.kotlin) modImplementation(libs.fabric.kotlin)
modImplementation(libs.moulconfig) modImplementation(libs.moulconfig)
modImplementation(libs.manninghamMills) modImplementation(libs.manninghamMills)
modImplementation(libs.basicMath)
include(libs.basicMath)
(modmenuSourceSet.modImplementationConfigurationName)(libs.modmenu) (modmenuSourceSet.modImplementationConfigurationName)(libs.modmenu)
(explosiveEnhancementSourceSet.modImplementationConfigurationName)(libs.explosiveenhancement) (explosiveEnhancementSourceSet.modImplementationConfigurationName)(libs.explosiveenhancement)
modImplementation(libs.hypixelmodapi) modImplementation(libs.hypixelmodapi)
@@ -234,13 +237,14 @@ dependencies {
(yaclSourceSet.modImplementationConfigurationName)(libs.yacl) (yaclSourceSet.modImplementationConfigurationName)(libs.yacl)
// Actual dependencies // Actual dependencies
modCompileOnly(libs.rei.api) { (reiSourceSet.modImplementationConfigurationName)(libs.rei.api) {
exclude(module = "architectury") exclude(module = "architectury")
exclude(module = "architectury-fabric") exclude(module = "architectury-fabric")
} }
nonModImplentation(libs.repoparser) nonModImplentation(libs.repoparser)
shadowMe(libs.repoparser) shadowMe(libs.repoparser)
fun ktor(mod: String) = "io.ktor:ktor-$mod-jvm:${libs.versions.ktor.get()}" 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-core"))!!)
transInclude(nonModImplentation(ktor("client-java"))!!) transInclude(nonModImplentation(ktor("client-java"))!!)
transInclude(nonModImplentation(ktor("serialization-kotlinx-json"))!!) 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 # Update from https://docs.isxander.dev/yet-another-config-lib/installing-yacl
yacl = "3.5.0+1.21-fabric" 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] [libraries]
minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" }
fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" } 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" } citresewn = { module = "maven.modrinth:cit-resewn", version.ref = "citresewn" }
femalegender = { module = "maven.modrinth:female-gender", version.ref = "femalegender" } femalegender = { module = "maven.modrinth:female-gender", version.ref = "femalegender" }
yacl = { module = "dev.isxander:yet-another-config-lib", version.ref = "yacl" } yacl = { module = "dev.isxander:yet-another-config-lib", version.ref = "yacl" }
basicMath = { module = "me.shedaniel.cloth:basic-math", version.ref = "basicMath" }
[bundles] [bundles]
runtime_required = [ runtime_required = [

View File

@@ -1,10 +1,10 @@
package moe.nea.firmament.compat.rei
package moe.nea.firmament.gui.entity
import me.shedaniel.math.Dimension import me.shedaniel.math.Dimension
import me.shedaniel.math.Point import me.shedaniel.math.Point
import me.shedaniel.math.Rectangle import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds 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.DrawContext
import net.minecraft.client.gui.Element import net.minecraft.client.gui.Element
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
@@ -19,7 +19,7 @@ class EntityWidget(val entity: LivingEntity, val point: Point) : WidgetWithBound
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
try { try {
if (!hasErrored) if (!hasErrored)
EntityRenderer.renderEntity(entity, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat()) EntityRenderer.renderEntity(entity, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat())
} catch (ex: Exception) { } catch (ex: Exception) {
EntityRenderer.logger.error("Failed to render constructed entity: $entity", ex) EntityRenderer.logger.error("Failed to render constructed entity: $entity", ex)
hasErrored = true hasErrored = true

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.plugins.REIClientPlugin
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry 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.events.HandledScreenPushREIEvent
import moe.nea.firmament.features.inventory.CraftingOverlay import moe.nea.firmament.features.inventory.CraftingOverlay
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
import moe.nea.firmament.rei.recipes.SBCraftingRecipe import moe.nea.firmament.compat.rei.recipes.SBCraftingRecipe
import moe.nea.firmament.rei.recipes.SBEssenceUpgradeRecipe import moe.nea.firmament.compat.rei.recipes.SBEssenceUpgradeRecipe
import moe.nea.firmament.rei.recipes.SBForgeRecipe import moe.nea.firmament.compat.rei.recipes.SBForgeRecipe
import moe.nea.firmament.rei.recipes.SBKatRecipe import moe.nea.firmament.compat.rei.recipes.SBKatRecipe
import moe.nea.firmament.rei.recipes.SBMobDropRecipe import moe.nea.firmament.compat.rei.recipes.SBMobDropRecipe
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.ScreenUtil import moe.nea.firmament.util.ScreenUtil
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
@@ -63,7 +64,7 @@ class FirmamentReiPlugin : REIClientPlugin {
MC.sendCommand("craft") MC.sendCommand("craft")
shouldReturn = false shouldReturn = false
} }
CraftingOverlay.setOverlay(screen as? GenericContainerScreen, display) CraftingOverlay.setOverlay(screen as? GenericContainerScreen, display.neuRecipe)
} }
if (context.isActuallyCrafting && useSuperCraft) { if (context.isActuallyCrafting && useSuperCraft) {
shouldReturn = false 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 * 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.DstFactor
import com.mojang.blaze3d.platform.GlStateManager.SrcFactor 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.Item
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.item.tooltip.TooltipType 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> { object NEUItemEntryRenderer : EntryRenderer<SBItemStack>, BatchedEntryRenderer<SBItemStack, BakedModel> {
override fun render( 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.EntrySerializer
import me.shedaniel.rei.api.common.entry.EntryStack import me.shedaniel.rei.api.common.entry.EntryStack
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
object NEUItemEntrySerializer : EntrySerializer<SBItemStack> { 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.NEUCraftingRecipe
import io.github.moulberry.repo.data.NEUForgeRecipe 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.client.view.ViewSearchBuilder
import me.shedaniel.rei.api.common.display.Display import me.shedaniel.rei.api.common.display.Display
import me.shedaniel.rei.api.common.entry.EntryStack import me.shedaniel.rei.api.common.entry.EntryStack
import moe.nea.firmament.rei.recipes.SBCraftingRecipe import moe.nea.firmament.compat.rei.recipes.SBCraftingRecipe
import moe.nea.firmament.rei.recipes.SBEssenceUpgradeRecipe import moe.nea.firmament.compat.rei.recipes.SBEssenceUpgradeRecipe
import moe.nea.firmament.rei.recipes.SBForgeRecipe import moe.nea.firmament.compat.rei.recipes.SBForgeRecipe
import moe.nea.firmament.rei.recipes.SBKatRecipe import moe.nea.firmament.compat.rei.recipes.SBKatRecipe
import moe.nea.firmament.rei.recipes.SBMobDropRecipe import moe.nea.firmament.compat.rei.recipes.SBMobDropRecipe
import moe.nea.firmament.repo.EssenceRecipeProvider import moe.nea.firmament.repo.EssenceRecipeProvider
import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
val SkyblockCraftingRecipeDynamicGenerator = 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 dev.architectury.event.CompoundEventResult
import me.shedaniel.math.Point 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 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.NEUCraftingRecipe
import io.github.moulberry.repo.data.NEUIngredient 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.block.Blocks
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.rei.SBItemEntryDefinition import moe.nea.firmament.compat.rei.SBItemEntryDefinition
class SBCraftingRecipe(override val neuRecipe: NEUCraftingRecipe) : SBRecipe() { class SBCraftingRecipe(override val neuRecipe: NEUCraftingRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier 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.Point
import me.shedaniel.math.Rectangle 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 me.shedaniel.rei.api.common.category.CategoryIdentifier
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.rei.SBItemEntryDefinition import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.rei.SBItemStack
import moe.nea.firmament.repo.EssenceRecipeProvider import moe.nea.firmament.repo.EssenceRecipeProvider
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
class SBEssenceUpgradeRecipe(override val neuRecipe: EssenceRecipeProvider.EssenceUpgradeRecipe) : SBRecipe() { 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 io.github.moulberry.repo.data.NEUForgeRecipe
import me.shedaniel.math.Point import me.shedaniel.math.Point
@@ -17,8 +17,8 @@ import kotlin.time.Duration.Companion.seconds
import net.minecraft.block.Blocks import net.minecraft.block.Blocks
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.rei.SBItemEntryDefinition import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.rei.plus import moe.nea.firmament.compat.rei.plus
class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() { class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier 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.moulberry.repo.data.NEUKatUpgradeRecipe
import io.github.notenoughupdates.moulconfig.common.IMinecraft 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.item.Items
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.rei.PetData import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.rei.SBItemEntryDefinition import moe.nea.firmament.repo.PetData
import moe.nea.firmament.rei.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.FirmFormatters import moe.nea.firmament.util.FirmFormatters
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SkyblockId 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 io.github.moulberry.repo.data.NEUMobDropRecipe
import me.shedaniel.math.Point import me.shedaniel.math.Point
@@ -15,8 +15,8 @@ import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.entity.EntityRenderer import moe.nea.firmament.gui.entity.EntityRenderer
import moe.nea.firmament.gui.entity.EntityWidget import moe.nea.firmament.compat.rei.EntityWidget
import moe.nea.firmament.rei.SBItemEntryDefinition import moe.nea.firmament.compat.rei.SBItemEntryDefinition
class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() { class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
@@ -73,8 +73,8 @@ class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
tt.removeAt(1) tt.removeAt(1)
add( add(
Widgets.withTooltip( Widgets.withTooltip(
EntityWidget(entity, Point(bounds.minX + 5, bounds.minY + 15)), EntityWidget(entity, Point(bounds.minX + 5, bounds.minY + 15)),
tt tt
) )
) )
} }

View File

@@ -1,12 +1,10 @@
package moe.nea.firmament.compat.rei.recipes
package moe.nea.firmament.rei.recipes
import io.github.moulberry.repo.data.NEUIngredient import io.github.moulberry.repo.data.NEUIngredient
import io.github.moulberry.repo.data.NEURecipe import io.github.moulberry.repo.data.NEURecipe
import me.shedaniel.rei.api.common.display.Display import me.shedaniel.rei.api.common.display.Display
import me.shedaniel.rei.api.common.entry.EntryIngredient 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 import moe.nea.firmament.util.SkyblockId
abstract class SBRecipe : Display { 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.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.gui.hud.MoulConfigHud import moe.nea.firmament.gui.hud.MoulConfigHud
import moe.nea.firmament.rei.SBItemEntryDefinition
import moe.nea.firmament.repo.ItemNameLookup import moe.nea.firmament.repo.ItemNameLookup
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SHORT_NUMBER_FORMAT import moe.nea.firmament.util.SHORT_NUMBER_FORMAT
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
@@ -197,9 +197,9 @@ object AnniversaryFeatures : FirmamentFeature {
} }
val itemStack = if (backedBy is Reward.Items) { val itemStack = if (backedBy is Reward.Items) {
SBItemEntryDefinition.getEntry(backedBy.item, backedBy.amount) SBItemStack(backedBy.item, backedBy.amount)
} else { } else {
SBItemEntryDefinition.getEntry(SkyblockId.NULL) SBItemStack(SkyblockId.NULL)
} }
@Bind @Bind
@@ -207,7 +207,7 @@ object AnniversaryFeatures : FirmamentFeature {
return when (backedBy) { return when (backedBy) {
is Reward.Coins -> "Coins" is Reward.Coins -> "Coins"
is Reward.EXP -> backedBy.skill 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 is Reward.Unknown -> backedBy.text
} }
} }

View File

@@ -1,5 +1,6 @@
package moe.nea.firmament.features.inventory package moe.nea.firmament.features.inventory
import io.github.moulberry.repo.data.NEUCraftingRecipe
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.util.Formatting 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.ScreenChangeEvent
import moe.nea.firmament.events.SlotRenderEvents import moe.nea.firmament.events.SlotRenderEvents
import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.rei.SBItemEntryDefinition
import moe.nea.firmament.rei.recipes.SBCraftingRecipe
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.skyblockId
object CraftingOverlay : FirmamentFeature { object CraftingOverlay : FirmamentFeature {
private var screen: GenericContainerScreen? = null private var screen: GenericContainerScreen? = null
private var recipe: SBCraftingRecipe? = null private var recipe: NEUCraftingRecipe? = null
private var useNextScreen = false private var useNextScreen = false
private val craftingOverlayIndices = listOf( private val craftingOverlayIndices = listOf(
10, 11, 12, 10, 11, 12,
@@ -24,7 +24,7 @@ object CraftingOverlay : FirmamentFeature {
) )
val CRAFTING_SCREEN_NAME = "Craft Item" val CRAFTING_SCREEN_NAME = "Craft Item"
fun setOverlay(screen: GenericContainerScreen?, recipe: SBCraftingRecipe) { fun setOverlay(screen: GenericContainerScreen?, recipe: NEUCraftingRecipe) {
this.screen = screen this.screen = screen
if (screen == null) { if (screen == null) {
useNextScreen = true useNextScreen = true
@@ -52,10 +52,12 @@ object CraftingOverlay : FirmamentFeature {
if (slot.inventory != screen?.screenHandler?.inventory) return if (slot.inventory != screen?.screenHandler?.inventory) return
val recipeIndex = craftingOverlayIndices.indexOf(slot.index) val recipeIndex = craftingOverlayIndices.indexOf(slot.index)
if (recipeIndex < 0) return if (recipeIndex < 0) return
val expectedItem = recipe.neuRecipe.inputs[recipeIndex] val expectedItem = recipe.inputs[recipeIndex]
val actualStack = slot.stack ?: ItemStack.EMPTY!! val actualStack = slot.stack ?: ItemStack.EMPTY!!
val actualEntry = SBItemEntryDefinition.getEntry(actualStack).value val actualEntry = SBItemStack(actualStack)
if ((actualEntry.skyblockId.neuItem != expectedItem.itemId || actualEntry.getStackSize() < expectedItem.amount) && expectedItem.amount.toInt() != 0) { if ((actualEntry.skyblockId != expectedItem.skyblockId || actualEntry.getStackSize() < expectedItem.amount)
&& expectedItem.amount.toInt() != 0
) {
event.context.fill( event.context.fill(
event.slot.x, event.slot.x,
event.slot.y, event.slot.y,
@@ -65,7 +67,7 @@ object CraftingOverlay : FirmamentFeature {
) )
} }
if (!slot.hasStack()) { 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.drawItem(itemStack, event.slot.x, event.slot.y)
event.context.drawItemInSlot( event.context.drawItemInSlot(
MC.font, MC.font,

View File

@@ -1,4 +1,3 @@
package moe.nea.firmament.gui.entity package moe.nea.firmament.gui.entity
import com.google.gson.JsonObject import com.google.gson.JsonObject
@@ -6,50 +5,49 @@ import net.minecraft.component.DataComponentTypes
import net.minecraft.component.type.DyedColorComponent import net.minecraft.component.type.DyedColorComponent
import net.minecraft.entity.EquipmentSlot import net.minecraft.entity.EquipmentSlot
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
import net.minecraft.item.ArmorItem
import net.minecraft.item.Item import net.minecraft.item.Item
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.item.Items import net.minecraft.item.Items
import moe.nea.firmament.rei.SBItemStack import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.mc.setEncodedSkullOwner import moe.nea.firmament.util.mc.setEncodedSkullOwner
import moe.nea.firmament.util.mc.zeroUUID import moe.nea.firmament.util.mc.zeroUUID
object ModifyEquipment : EntityModifier { object ModifyEquipment : EntityModifier {
val names = mapOf( val names = mapOf(
"hand" to EquipmentSlot.MAINHAND, "hand" to EquipmentSlot.MAINHAND,
"helmet" to EquipmentSlot.HEAD, "helmet" to EquipmentSlot.HEAD,
"chestplate" to EquipmentSlot.CHEST, "chestplate" to EquipmentSlot.CHEST,
"leggings" to EquipmentSlot.LEGS, "leggings" to EquipmentSlot.LEGS,
"feet" to EquipmentSlot.FEET, "feet" to EquipmentSlot.FEET,
) )
override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity { override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
names.forEach { (key, slot) -> names.forEach { (key, slot) ->
info[key]?.let { info[key]?.let {
entity.equipStack(slot, createItem(it.asString)) entity.equipStack(slot, createItem(it.asString))
} }
} }
return entity return entity
} }
private fun createItem(item: String): ItemStack { private fun createItem(item: String): ItemStack {
val split = item.split("#") val split = item.split("#")
if (split.size != 2) return SBItemStack(SkyblockId(item)).asImmutableItemStack() if (split.size != 2) return SBItemStack(SkyblockId(item)).asImmutableItemStack()
val (type, data) = split val (type, data) = split
return when (type) { return when (type) {
"SKULL" -> ItemStack(Items.PLAYER_HEAD).also { it.setEncodedSkullOwner(zeroUUID, data) } "SKULL" -> ItemStack(Items.PLAYER_HEAD).also { it.setEncodedSkullOwner(zeroUUID, data) }
"LEATHER_LEGGINGS" -> coloredLeatherArmor(Items.LEATHER_LEGGINGS, data) "LEATHER_LEGGINGS" -> coloredLeatherArmor(Items.LEATHER_LEGGINGS, data)
"LEATHER_BOOTS" -> coloredLeatherArmor(Items.LEATHER_BOOTS, data) "LEATHER_BOOTS" -> coloredLeatherArmor(Items.LEATHER_BOOTS, data)
"LEATHER_HELMET" -> coloredLeatherArmor(Items.LEATHER_HELMET, data) "LEATHER_HELMET" -> coloredLeatherArmor(Items.LEATHER_HELMET, data)
"LEATHER_CHESTPLATE" -> coloredLeatherArmor(Items.LEATHER_CHESTPLATE, data) "LEATHER_CHESTPLATE" -> coloredLeatherArmor(Items.LEATHER_CHESTPLATE, data)
else -> error("Unknown leather piece: $type") else -> error("Unknown leather piece: $type")
} }
} }
private fun coloredLeatherArmor(leatherArmor: Item, data: String): ItemStack { private fun coloredLeatherArmor(leatherArmor: Item, data: String): ItemStack {
val stack = ItemStack(leatherArmor) val stack = ItemStack(leatherArmor)
stack.set(DataComponentTypes.DYED_COLOR, DyedColorComponent(data.toInt(16), false)) stack.set(DataComponentTypes.DYED_COLOR, DyedColorComponent(data.toInt(16), false))
return stack return stack
} }
} }

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.Firmament.logger
import moe.nea.firmament.events.ReloadRegistrationEvent import moe.nea.firmament.events.ReloadRegistrationEvent
import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.rei.PetData
import moe.nea.firmament.util.MinecraftDispatcher import moe.nea.firmament.util.MinecraftDispatcher
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
@@ -139,9 +138,9 @@ object RepoManager {
return null return null
} }
val intIndex = rarityIndex.toInt() 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 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 package moe.nea.firmament.util
import me.shedaniel.math.impl.PointHelper import com.google.auto.service.AutoService
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.client.gui.screen.ingame.HandledScreen
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen 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? val HandledScreen<*>.focusedItemStack: ItemStack?
get() { get() =
this as AccessorHandledScreen HoveredItemStackProvider.allValidInstances
val vanillaSlot = this.focusedSlot_Firmament?.stack .firstNotNullOfOrNull { it.provideHoveredItemStack(this) }
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)
}
}

View File

@@ -2,6 +2,7 @@
package moe.nea.firmament.util 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.NEUItem
import io.github.moulberry.repo.data.Rarity import io.github.moulberry.repo.data.Rarity
import java.util.Optional import java.util.Optional
@@ -61,7 +62,8 @@ value class SkyblockId(val neuItem: String) {
} }
companion object { 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() private val bazaarEnchantmentRegex = "ENCHANTMENT_(\\D*)_(\\d+)".toRegex()
val NULL: SkyblockId = SkyblockId("null") val NULL: SkyblockId = SkyblockId("null")
val PET_NULL: SkyblockId = SkyblockId("null_pet") val PET_NULL: SkyblockId = SkyblockId("null_pet")
@@ -70,6 +72,7 @@ value class SkyblockId(val neuItem: String) {
} }
val NEUItem.skyblockId get() = SkyblockId(skyblockItemId) val NEUItem.skyblockId get() = SkyblockId(skyblockItemId)
val NEUIngredient.skyblockId get() = SkyblockId(itemId)
fun NEUItem.guessRecipeId(): String? { fun NEUItem.guessRecipeId(): String? {
if (!skyblockItemId.contains(";")) return skyblockItemId if (!skyblockItemId.contains(";")) return skyblockItemId

View File

@@ -2,10 +2,13 @@ package moe.nea.firmament.util.compatloader
import java.util.ServiceLoader import java.util.ServiceLoader
import net.fabricmc.loader.api.FabricLoader import net.fabricmc.loader.api.FabricLoader
import kotlin.reflect.KClass
import kotlin.streams.asSequence import kotlin.streams.asSequence
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
abstract class CompatLoader<T : Any>(val kClass: Class<T>) { abstract class CompatLoader<T : Any>(val kClass: Class<T>) {
constructor(kClass: KClass<T>) : this(kClass.java)
val loader: ServiceLoader<T> = ServiceLoader.load(kClass) val loader: ServiceLoader<T> = ServiceLoader.load(kClass)
val allValidInstances by lazy { val allValidInstances by lazy {
loader.reload() loader.reload()

View File

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