Add pet upgrade cost recipes
This commit is contained in:
10
.reuse/dep5
10
.reuse/dep5
@@ -1,10 +0,0 @@
|
|||||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|
||||||
Upstream-Name: Firmament
|
|
||||||
Upstream-Contact: Linnea Gräf <nea@nea.moe>
|
|
||||||
Source: https://github.com/romangraef/Firmament
|
|
||||||
|
|
||||||
# Sample paragraph, commented out:
|
|
||||||
#
|
|
||||||
# Files: src/*
|
|
||||||
# Copyright: $YEAR $NAME <$CONTACT>
|
|
||||||
# License: ...
|
|
||||||
9
REUSE.toml
Normal file
9
REUSE.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
#
|
||||||
|
#SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
version = 1
|
||||||
|
SPDX-PackageName = "Firmament"
|
||||||
|
SPDX-PackageSupplier = "Linnea Gräf <nea@nea.moe>"
|
||||||
|
SPDX-PackageDownloadLocation = "https://github.com/romangraef/Firmament"
|
||||||
|
annotations = []
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
* 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: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
@@ -46,7 +47,7 @@ object CraftingOverlay : FirmamentFeature {
|
|||||||
val expectedItem = recipe.neuRecipe.inputs[recipeIndex]
|
val expectedItem = recipe.neuRecipe.inputs[recipeIndex]
|
||||||
val actualStack = slot.stack ?: ItemStack.EMPTY!!
|
val actualStack = slot.stack ?: ItemStack.EMPTY!!
|
||||||
val actualEntry = SBItemEntryDefinition.getEntry(actualStack).value
|
val actualEntry = SBItemEntryDefinition.getEntry(actualStack).value
|
||||||
if ((actualEntry.skyblockId.neuItem != expectedItem.itemId || actualEntry.stackSize < expectedItem.amount) && expectedItem.amount.toInt() != 0) {
|
if ((actualEntry.skyblockId.neuItem != expectedItem.itemId || 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,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ 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.rei.recipes.SBCraftingRecipe
|
||||||
import moe.nea.firmament.rei.recipes.SBForgeRecipe
|
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.rei.recipes.SBMobDropRecipe
|
||||||
import moe.nea.firmament.repo.RepoManager
|
import moe.nea.firmament.repo.RepoManager
|
||||||
import moe.nea.firmament.util.SkyblockId
|
import moe.nea.firmament.util.SkyblockId
|
||||||
@@ -70,6 +71,7 @@ class FirmamentReiPlugin : REIClientPlugin {
|
|||||||
registry.add(SBCraftingRecipe.Category)
|
registry.add(SBCraftingRecipe.Category)
|
||||||
registry.add(SBForgeRecipe.Category)
|
registry.add(SBForgeRecipe.Category)
|
||||||
registry.add(SBMobDropRecipe.Category)
|
registry.add(SBMobDropRecipe.Category)
|
||||||
|
registry.add(SBKatRecipe.Category)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerExclusionZones(zones: ExclusionZones) {
|
override fun registerExclusionZones(zones: ExclusionZones) {
|
||||||
@@ -80,14 +82,16 @@ class FirmamentReiPlugin : REIClientPlugin {
|
|||||||
override fun registerDisplays(registry: DisplayRegistry) {
|
override fun registerDisplays(registry: DisplayRegistry) {
|
||||||
registry.registerDisplayGenerator(
|
registry.registerDisplayGenerator(
|
||||||
SBCraftingRecipe.Category.catIdentifier,
|
SBCraftingRecipe.Category.catIdentifier,
|
||||||
SkyblockCraftingRecipeDynamicGenerator
|
SkyblockCraftingRecipeDynamicGenerator)
|
||||||
)
|
|
||||||
registry.registerDisplayGenerator(
|
registry.registerDisplayGenerator(
|
||||||
SBForgeRecipe.Category.categoryIdentifier,
|
SBForgeRecipe.Category.categoryIdentifier,
|
||||||
SkyblockForgeRecipeDynamicGenerator
|
SkyblockForgeRecipeDynamicGenerator)
|
||||||
)
|
registry.registerDisplayGenerator(
|
||||||
registry.registerDisplayGenerator(SBMobDropRecipe.Category.categoryIdentifier,
|
SBMobDropRecipe.Category.categoryIdentifier,
|
||||||
SkyblockMobDropRecipeDynamicGenerator)
|
SkyblockMobDropRecipeDynamicGenerator)
|
||||||
|
registry.registerDisplayGenerator(
|
||||||
|
SBKatRecipe.Category.categoryIdentifier,
|
||||||
|
SkyblockKatRecipeDynamicGenerator)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerCollapsibleEntries(registry: CollapsibleEntryRegistry) {
|
override fun registerCollapsibleEntries(registry: CollapsibleEntryRegistry) {
|
||||||
|
|||||||
@@ -47,13 +47,13 @@ object NEUItemEntryRenderer : EntryRenderer<SBItemStack>, BatchedEntryRenderer<S
|
|||||||
val minecraft = MinecraftClient.getInstance()
|
val minecraft = MinecraftClient.getInstance()
|
||||||
|
|
||||||
override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
|
override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
|
||||||
return Tooltip.create(
|
val stack = entry.value.asImmutableItemStack()
|
||||||
entry.asItemEntry().value.getTooltip(
|
val lore = stack.getTooltip(
|
||||||
Item.TooltipContext.DEFAULT,
|
Item.TooltipContext.DEFAULT,
|
||||||
null,
|
null,
|
||||||
TooltipType.BASIC
|
TooltipType.BASIC
|
||||||
)
|
)
|
||||||
)
|
return Tooltip.create(lore)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getExtraData(entry: EntryStack<SBItemStack>): BakedModel {
|
override fun getExtraData(entry: EntryStack<SBItemStack>): BakedModel {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
* 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: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
@@ -27,7 +28,7 @@ object NEUItemEntrySerializer : EntrySerializer<SBItemStack> {
|
|||||||
override fun save(entry: EntryStack<SBItemStack>, value: SBItemStack): NbtCompound {
|
override fun save(entry: EntryStack<SBItemStack>, value: SBItemStack): NbtCompound {
|
||||||
return NbtCompound().apply {
|
return NbtCompound().apply {
|
||||||
putString(SKYBLOCK_ID_ENTRY, value.skyblockId.neuItem)
|
putString(SKYBLOCK_ID_ENTRY, value.skyblockId.neuItem)
|
||||||
putInt(SKYBLOCK_ITEM_COUNT, value.stackSize)
|
putInt(SKYBLOCK_ITEM_COUNT, value.getStackSize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ data class PetData(
|
|||||||
fun fromHypixel(petInfo: HypixelPetInfo) = PetData(
|
fun fromHypixel(petInfo: HypixelPetInfo) = PetData(
|
||||||
petInfo.tier, petInfo.type, petInfo.exp,
|
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) }
|
val levelData by lazy { ExpLadders.getExpLadder(petId, rarity).getPetLevel(exp) }
|
||||||
@@ -54,10 +57,22 @@ data class PetData(
|
|||||||
data class SBItemStack(
|
data class SBItemStack(
|
||||||
val skyblockId: SkyblockId,
|
val skyblockId: SkyblockId,
|
||||||
val neuItem: NEUItem?,
|
val neuItem: NEUItem?,
|
||||||
val stackSize: Int,
|
private var stackSize: Int,
|
||||||
val petData: PetData?,
|
private var petData: PetData?,
|
||||||
val extraLore: List<Text> = emptyList(),
|
val extraLore: List<Text> = emptyList(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
fun getStackSize() = stackSize
|
||||||
|
fun setStackSize(newSize: Int) {
|
||||||
|
this.stackSize = stackSize
|
||||||
|
this.itemStack_ = null
|
||||||
|
}
|
||||||
|
fun getPetData() = petData
|
||||||
|
fun setPetData(petData: PetData?) {
|
||||||
|
this.petData = petData
|
||||||
|
this.itemStack_ = null
|
||||||
|
}
|
||||||
|
|
||||||
constructor(skyblockId: SkyblockId, petData: PetData) : this(
|
constructor(skyblockId: SkyblockId, petData: PetData) : this(
|
||||||
skyblockId,
|
skyblockId,
|
||||||
RepoManager.getNEUItem(skyblockId),
|
RepoManager.getNEUItem(skyblockId),
|
||||||
@@ -87,7 +102,7 @@ data class SBItemStack(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun injectReplacementDataForPets(replacementData: MutableMap<String, String>) {
|
private fun injectReplacementDataForPets(replacementData: MutableMap<String, String>) {
|
||||||
if (petData == null) return
|
val petData = this.petData ?: return
|
||||||
val petInfo = RepoManager.neuRepo.constants.petNumbers[petData.petId]?.get(petData.rarity) ?: return
|
val petInfo = RepoManager.neuRepo.constants.petNumbers[petData.petId]?.get(petData.rarity) ?: return
|
||||||
if (petData.isStub) {
|
if (petData.isStub) {
|
||||||
val mapLow = mutableMapOf<String, String>()
|
val mapLow = mutableMapOf<String, String>()
|
||||||
@@ -105,14 +120,23 @@ data class SBItemStack(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val itemStack: ItemStack by lazy(LazyThreadSafetyMode.NONE) {
|
|
||||||
|
private var itemStack_: ItemStack? = null
|
||||||
|
|
||||||
|
private val itemStack: ItemStack
|
||||||
|
get() {
|
||||||
|
val itemStack = itemStack_ ?: run {
|
||||||
if (skyblockId == SkyblockId.COINS)
|
if (skyblockId == SkyblockId.COINS)
|
||||||
return@lazy ItemCache.coinItem(stackSize).also { it.appendLore(extraLore) }
|
return@run ItemCache.coinItem(stackSize).also { it.appendLore(extraLore) }
|
||||||
val replacementData = mutableMapOf<String, String>()
|
val replacementData = mutableMapOf<String, String>()
|
||||||
injectReplacementDataForPets(replacementData)
|
injectReplacementDataForPets(replacementData)
|
||||||
return@lazy neuItem.asItemStack(idHint = skyblockId, replacementData).copyWithCount(stackSize)
|
return@run neuItem.asItemStack(idHint = skyblockId, replacementData).copyWithCount(stackSize)
|
||||||
.also { it.appendLore(extraLore) }
|
.also { it.appendLore(extraLore) }
|
||||||
}
|
}
|
||||||
|
if (itemStack_ == null)
|
||||||
|
itemStack_ = itemStack
|
||||||
|
return itemStack
|
||||||
|
}
|
||||||
|
|
||||||
fun asImmutableItemStack(): ItemStack {
|
fun asImmutableItemStack(): ItemStack {
|
||||||
return itemStack
|
return itemStack
|
||||||
@@ -125,7 +149,7 @@ data class SBItemStack(
|
|||||||
|
|
||||||
object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
|
object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
|
||||||
override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean {
|
override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean {
|
||||||
return o1.skyblockId == o2.skyblockId && o1.stackSize == o2.stackSize
|
return o1.skyblockId == o2.skyblockId && o1.getStackSize() == o2.getStackSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
|
override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
|
||||||
@@ -167,7 +191,7 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isEmpty(entry: EntryStack<SBItemStack>?, value: SBItemStack): Boolean {
|
override fun isEmpty(entry: EntryStack<SBItemStack>?, value: SBItemStack): Boolean {
|
||||||
return value.stackSize == 0
|
return value.getStackSize() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getIdentifier(entry: EntryStack<SBItemStack>?, value: SBItemStack): Identifier {
|
override fun getIdentifier(entry: EntryStack<SBItemStack>?, value: SBItemStack): Identifier {
|
||||||
|
|||||||
@@ -9,32 +9,34 @@ package moe.nea.firmament.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
|
||||||
|
import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
|
||||||
import io.github.moulberry.repo.data.NEUMobDropRecipe
|
import io.github.moulberry.repo.data.NEUMobDropRecipe
|
||||||
import io.github.moulberry.repo.data.NEURecipe
|
import io.github.moulberry.repo.data.NEURecipe
|
||||||
import java.util.*
|
import java.util.Optional
|
||||||
import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator
|
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.rei.recipes.SBCraftingRecipe
|
||||||
import moe.nea.firmament.rei.recipes.SBForgeRecipe
|
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.rei.recipes.SBMobDropRecipe
|
||||||
import moe.nea.firmament.repo.RepoManager
|
import moe.nea.firmament.repo.RepoManager
|
||||||
|
|
||||||
|
|
||||||
val SkyblockCraftingRecipeDynamicGenerator = neuDisplayGenerator<SBCraftingRecipe, NEUCraftingRecipe> {
|
val SkyblockCraftingRecipeDynamicGenerator =
|
||||||
SBCraftingRecipe(it)
|
neuDisplayGenerator<SBCraftingRecipe, NEUCraftingRecipe> { SBCraftingRecipe(it) }
|
||||||
}
|
|
||||||
|
|
||||||
val SkyblockForgeRecipeDynamicGenerator = neuDisplayGenerator<SBForgeRecipe, NEUForgeRecipe> {
|
val SkyblockForgeRecipeDynamicGenerator =
|
||||||
SBForgeRecipe(it)
|
neuDisplayGenerator<SBForgeRecipe, NEUForgeRecipe> { SBForgeRecipe(it) }
|
||||||
}
|
|
||||||
|
|
||||||
val SkyblockMobDropRecipeDynamicGenerator = neuDisplayGenerator<SBMobDropRecipe, NEUMobDropRecipe> {
|
val SkyblockMobDropRecipeDynamicGenerator =
|
||||||
SBMobDropRecipe(it)
|
neuDisplayGenerator<SBMobDropRecipe, NEUMobDropRecipe> { SBMobDropRecipe(it) }
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(noinline mapper: (T) -> D) =
|
val SkyblockKatRecipeDynamicGenerator =
|
||||||
|
neuDisplayGenerator<SBKatRecipe, NEUKatUpgradeRecipe> { SBKatRecipe(it) }
|
||||||
|
|
||||||
|
inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(crossinline mapper: (T) -> D) =
|
||||||
object : DynamicDisplayGenerator<D> {
|
object : DynamicDisplayGenerator<D> {
|
||||||
override fun getRecipeFor(entry: EntryStack<*>): Optional<List<D>> {
|
override fun getRecipeFor(entry: EntryStack<*>): Optional<List<D>> {
|
||||||
if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
|
if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
|
||||||
@@ -47,7 +49,7 @@ inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(noinline map
|
|||||||
override fun generate(builder: ViewSearchBuilder): Optional<List<D>> {
|
override fun generate(builder: ViewSearchBuilder): Optional<List<D>> {
|
||||||
if (SBCraftingRecipe.Category.catIdentifier !in builder.categories) return Optional.empty()
|
if (SBCraftingRecipe.Category.catIdentifier !in builder.categories) return Optional.empty()
|
||||||
return Optional.of(
|
return Optional.of(
|
||||||
RepoManager.getAllRecipes().filterIsInstance<T>().map(mapper)
|
RepoManager.getAllRecipes().filterIsInstance<T>().map { mapper(it) }
|
||||||
.toList()
|
.toList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
229
src/main/kotlin/moe/nea/firmament/rei/recipes/SBKatRecipe.kt
Normal file
229
src/main/kotlin/moe/nea/firmament/rei/recipes/SBKatRecipe.kt
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
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()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ package moe.nea.firmament.util.item
|
|||||||
import com.mojang.authlib.GameProfile
|
import com.mojang.authlib.GameProfile
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture
|
||||||
import com.mojang.authlib.properties.Property
|
import com.mojang.authlib.properties.Property
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -63,10 +63,12 @@ fun ItemStack.setEncodedSkullOwner(uuid: UUID, encodedData: String) {
|
|||||||
val zeroUUID = UUID.fromString("d3cb85e2-3075-48a1-b213-a9bfb62360c1")
|
val zeroUUID = UUID.fromString("d3cb85e2-3075-48a1-b213-a9bfb62360c1")
|
||||||
fun ItemStack.setSkullOwner(uuid: UUID, url: String) {
|
fun ItemStack.setSkullOwner(uuid: UUID, url: String) {
|
||||||
assert(this.item == Items.PLAYER_HEAD)
|
assert(this.item == Items.PLAYER_HEAD)
|
||||||
val gameProfile = GameProfile(uuid, "LameGuy123")
|
val gameProfile = GameProfile(uuid, "nea89")
|
||||||
gameProfile.setTextures(
|
gameProfile.setTextures(
|
||||||
MinecraftTexturesPayloadKt(
|
MinecraftTexturesPayloadKt(
|
||||||
mapOf(MinecraftProfileTexture.Type.SKIN to MinecraftProfileTextureKt(url))
|
textures = mapOf(MinecraftProfileTexture.Type.SKIN to MinecraftProfileTextureKt(url)),
|
||||||
|
profileId = uuid,
|
||||||
|
profileName = "nea89",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
this.set(DataComponentTypes.PROFILE, ProfileComponent(gameProfile))
|
this.set(DataComponentTypes.PROFILE, ProfileComponent(gameProfile))
|
||||||
|
|||||||
Reference in New Issue
Block a user