Make REI optional
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
package moe.nea.firmament.gui.entity
|
||||
|
||||
import me.shedaniel.math.Dimension
|
||||
import me.shedaniel.math.Point
|
||||
import me.shedaniel.math.Rectangle
|
||||
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.Element
|
||||
import net.minecraft.entity.LivingEntity
|
||||
|
||||
class EntityWidget(val entity: LivingEntity, val point: Point) : WidgetWithBounds() {
|
||||
override fun children(): List<Element> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
var hasErrored = false
|
||||
|
||||
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
try {
|
||||
if (!hasErrored)
|
||||
EntityRenderer.renderEntity(entity, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat())
|
||||
} catch (ex: Exception) {
|
||||
EntityRenderer.logger.error("Failed to render constructed entity: $entity", ex)
|
||||
hasErrored = true
|
||||
}
|
||||
if (hasErrored) {
|
||||
context.fill(point.x, point.y, point.x + 50, point.y + 80, 0xFFAA2222.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBounds(): Rectangle {
|
||||
return Rectangle(point, Dimension(50, 80))
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package moe.nea.firmament.gui.entity
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
@@ -6,50 +5,49 @@ import net.minecraft.component.DataComponentTypes
|
||||
import net.minecraft.component.type.DyedColorComponent
|
||||
import net.minecraft.entity.EquipmentSlot
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.item.ArmorItem
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import moe.nea.firmament.rei.SBItemStack
|
||||
import moe.nea.firmament.repo.SBItemStack
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
import moe.nea.firmament.util.mc.setEncodedSkullOwner
|
||||
import moe.nea.firmament.util.mc.zeroUUID
|
||||
|
||||
object ModifyEquipment : EntityModifier {
|
||||
val names = mapOf(
|
||||
"hand" to EquipmentSlot.MAINHAND,
|
||||
"helmet" to EquipmentSlot.HEAD,
|
||||
"chestplate" to EquipmentSlot.CHEST,
|
||||
"leggings" to EquipmentSlot.LEGS,
|
||||
"feet" to EquipmentSlot.FEET,
|
||||
)
|
||||
val names = mapOf(
|
||||
"hand" to EquipmentSlot.MAINHAND,
|
||||
"helmet" to EquipmentSlot.HEAD,
|
||||
"chestplate" to EquipmentSlot.CHEST,
|
||||
"leggings" to EquipmentSlot.LEGS,
|
||||
"feet" to EquipmentSlot.FEET,
|
||||
)
|
||||
|
||||
override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
|
||||
names.forEach { (key, slot) ->
|
||||
info[key]?.let {
|
||||
entity.equipStack(slot, createItem(it.asString))
|
||||
}
|
||||
}
|
||||
return entity
|
||||
}
|
||||
override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
|
||||
names.forEach { (key, slot) ->
|
||||
info[key]?.let {
|
||||
entity.equipStack(slot, createItem(it.asString))
|
||||
}
|
||||
}
|
||||
return entity
|
||||
}
|
||||
|
||||
private fun createItem(item: String): ItemStack {
|
||||
val split = item.split("#")
|
||||
if (split.size != 2) return SBItemStack(SkyblockId(item)).asImmutableItemStack()
|
||||
val (type, data) = split
|
||||
return when (type) {
|
||||
"SKULL" -> ItemStack(Items.PLAYER_HEAD).also { it.setEncodedSkullOwner(zeroUUID, data) }
|
||||
"LEATHER_LEGGINGS" -> coloredLeatherArmor(Items.LEATHER_LEGGINGS, data)
|
||||
"LEATHER_BOOTS" -> coloredLeatherArmor(Items.LEATHER_BOOTS, data)
|
||||
"LEATHER_HELMET" -> coloredLeatherArmor(Items.LEATHER_HELMET, data)
|
||||
"LEATHER_CHESTPLATE" -> coloredLeatherArmor(Items.LEATHER_CHESTPLATE, data)
|
||||
else -> error("Unknown leather piece: $type")
|
||||
}
|
||||
}
|
||||
private fun createItem(item: String): ItemStack {
|
||||
val split = item.split("#")
|
||||
if (split.size != 2) return SBItemStack(SkyblockId(item)).asImmutableItemStack()
|
||||
val (type, data) = split
|
||||
return when (type) {
|
||||
"SKULL" -> ItemStack(Items.PLAYER_HEAD).also { it.setEncodedSkullOwner(zeroUUID, data) }
|
||||
"LEATHER_LEGGINGS" -> coloredLeatherArmor(Items.LEATHER_LEGGINGS, data)
|
||||
"LEATHER_BOOTS" -> coloredLeatherArmor(Items.LEATHER_BOOTS, data)
|
||||
"LEATHER_HELMET" -> coloredLeatherArmor(Items.LEATHER_HELMET, data)
|
||||
"LEATHER_CHESTPLATE" -> coloredLeatherArmor(Items.LEATHER_CHESTPLATE, data)
|
||||
else -> error("Unknown leather piece: $type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun coloredLeatherArmor(leatherArmor: Item, data: String): ItemStack {
|
||||
val stack = ItemStack(leatherArmor)
|
||||
stack.set(DataComponentTypes.DYED_COLOR, DyedColorComponent(data.toInt(16), false))
|
||||
return stack
|
||||
}
|
||||
private fun coloredLeatherArmor(leatherArmor: Item, data: String): ItemStack {
|
||||
val stack = ItemStack(leatherArmor)
|
||||
stack.set(DataComponentTypes.DYED_COLOR, DyedColorComponent(data.toInt(16), false))
|
||||
return stack
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
package moe.nea.firmament.rei
|
||||
|
||||
import me.shedaniel.rei.api.client.plugins.REIClientPlugin
|
||||
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry
|
||||
import me.shedaniel.rei.api.client.registry.display.DisplayRegistry
|
||||
import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry
|
||||
import me.shedaniel.rei.api.client.registry.entry.EntryRegistry
|
||||
import me.shedaniel.rei.api.client.registry.screen.ExclusionZones
|
||||
import me.shedaniel.rei.api.client.registry.screen.OverlayDecider
|
||||
import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
|
||||
import me.shedaniel.rei.api.client.registry.transfer.TransferHandler
|
||||
import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry
|
||||
import me.shedaniel.rei.api.common.entry.EntryStack
|
||||
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
|
||||
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Identifier
|
||||
import moe.nea.firmament.events.HandledScreenPushREIEvent
|
||||
import moe.nea.firmament.features.inventory.CraftingOverlay
|
||||
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
|
||||
import moe.nea.firmament.rei.recipes.SBCraftingRecipe
|
||||
import moe.nea.firmament.rei.recipes.SBEssenceUpgradeRecipe
|
||||
import moe.nea.firmament.rei.recipes.SBForgeRecipe
|
||||
import moe.nea.firmament.rei.recipes.SBKatRecipe
|
||||
import moe.nea.firmament.rei.recipes.SBMobDropRecipe
|
||||
import moe.nea.firmament.repo.RepoManager
|
||||
import moe.nea.firmament.util.MC
|
||||
import moe.nea.firmament.util.ScreenUtil
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
import moe.nea.firmament.util.guessRecipeId
|
||||
import moe.nea.firmament.util.skyblockId
|
||||
import moe.nea.firmament.util.unformattedString
|
||||
|
||||
|
||||
class FirmamentReiPlugin : REIClientPlugin {
|
||||
|
||||
companion object {
|
||||
fun EntryStack<SBItemStack>.asItemEntry(): EntryStack<ItemStack> {
|
||||
return EntryStack.of(VanillaEntryTypes.ITEM, value.asImmutableItemStack())
|
||||
}
|
||||
|
||||
val SKYBLOCK_ITEM_TYPE_ID = Identifier.of("firmament", "skyblockitems")
|
||||
}
|
||||
|
||||
override fun registerTransferHandlers(registry: TransferHandlerRegistry) {
|
||||
registry.register(TransferHandler { context ->
|
||||
val screen = context.containerScreen
|
||||
val display = context.display
|
||||
if (display !is SBCraftingRecipe) return@TransferHandler TransferHandler.Result.createNotApplicable()
|
||||
val neuItem = RepoManager.getNEUItem(SkyblockId(display.neuRecipe.output.itemId))
|
||||
?: error("Could not find neu item ${display.neuRecipe.output.itemId} which is used in a recipe output")
|
||||
val useSuperCraft = context.isStackedCrafting || RepoManager.Config.alwaysSuperCraft
|
||||
if (neuItem.isVanilla && useSuperCraft) return@TransferHandler TransferHandler.Result.createFailed(Text.translatable(
|
||||
"firmament.recipe.novanilla"))
|
||||
var shouldReturn = true
|
||||
if (context.isActuallyCrafting && !useSuperCraft) {
|
||||
if (screen !is GenericContainerScreen || screen.title?.unformattedString != CraftingOverlay.CRAFTING_SCREEN_NAME) {
|
||||
MC.sendCommand("craft")
|
||||
shouldReturn = false
|
||||
}
|
||||
CraftingOverlay.setOverlay(screen as? GenericContainerScreen, display)
|
||||
}
|
||||
if (context.isActuallyCrafting && useSuperCraft) {
|
||||
shouldReturn = false
|
||||
MC.sendCommand("viewrecipe ${neuItem.guessRecipeId()}")
|
||||
}
|
||||
return@TransferHandler TransferHandler.Result.createSuccessful().blocksFurtherHandling(shouldReturn)
|
||||
})
|
||||
}
|
||||
|
||||
override fun registerEntryTypes(registry: EntryTypeRegistry) {
|
||||
registry.register(SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition)
|
||||
}
|
||||
|
||||
override fun registerCategories(registry: CategoryRegistry) {
|
||||
registry.add(SBCraftingRecipe.Category)
|
||||
registry.add(SBForgeRecipe.Category)
|
||||
registry.add(SBMobDropRecipe.Category)
|
||||
registry.add(SBKatRecipe.Category)
|
||||
registry.add(SBEssenceUpgradeRecipe.Category)
|
||||
}
|
||||
|
||||
override fun registerExclusionZones(zones: ExclusionZones) {
|
||||
zones.register(HandledScreen::class.java) { HandledScreenPushREIEvent.publish(HandledScreenPushREIEvent(it)).rectangles }
|
||||
zones.register(StorageOverlayScreen::class.java) { it.getBounds() }
|
||||
}
|
||||
|
||||
override fun registerDisplays(registry: DisplayRegistry) {
|
||||
registry.registerDisplayGenerator(
|
||||
SBCraftingRecipe.Category.catIdentifier,
|
||||
SkyblockCraftingRecipeDynamicGenerator)
|
||||
registry.registerDisplayGenerator(
|
||||
SBForgeRecipe.Category.categoryIdentifier,
|
||||
SkyblockForgeRecipeDynamicGenerator)
|
||||
registry.registerDisplayGenerator(
|
||||
SBMobDropRecipe.Category.categoryIdentifier,
|
||||
SkyblockMobDropRecipeDynamicGenerator)
|
||||
registry.registerDisplayGenerator(
|
||||
SBKatRecipe.Category.categoryIdentifier,
|
||||
SkyblockKatRecipeDynamicGenerator)
|
||||
registry.registerDisplayGenerator(
|
||||
SBEssenceUpgradeRecipe.Category.categoryIdentifier,
|
||||
SkyblockEssenceRecipeDynamicGenerator
|
||||
)
|
||||
}
|
||||
|
||||
override fun registerCollapsibleEntries(registry: CollapsibleEntryRegistry) {
|
||||
if (!RepoManager.Config.disableItemGroups)
|
||||
RepoManager.neuRepo.constants.parents.parents
|
||||
.forEach { (parent, children) ->
|
||||
registry.group(
|
||||
SkyblockId(parent).identifier,
|
||||
Text.literal(RepoManager.getNEUItem(SkyblockId(parent))?.displayName ?: parent),
|
||||
(children + parent).map { SBItemEntryDefinition.getEntry(SkyblockId(it)) })
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerScreens(registry: ScreenRegistry) {
|
||||
registry.registerDecider(object : OverlayDecider {
|
||||
override fun <R : Screen?> isHandingScreen(screen: Class<R>?): Boolean {
|
||||
return screen == StorageOverlayScreen::class.java
|
||||
}
|
||||
|
||||
override fun <R : Screen?> shouldScreenBeOverlaid(screen: R): ActionResult {
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
})
|
||||
registry.registerFocusedStack(SkyblockItemIdFocusedStackProvider)
|
||||
}
|
||||
|
||||
override fun registerEntries(registry: EntryRegistry) {
|
||||
registry.removeEntryIf { true }
|
||||
RepoManager.neuRepo.items?.items?.values?.forEach { neuItem ->
|
||||
registry.addEntry(SBItemEntryDefinition.getEntry(neuItem.skyblockId))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2023 shedaniel <daniel@shedaniel.me>
|
||||
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
||||
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
package moe.nea.firmament.rei
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager.DstFactor
|
||||
import com.mojang.blaze3d.platform.GlStateManager.SrcFactor
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import me.shedaniel.math.Rectangle
|
||||
import me.shedaniel.rei.api.client.entry.renderer.BatchedEntryRenderer
|
||||
import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Tooltip
|
||||
import me.shedaniel.rei.api.client.gui.widgets.TooltipContext
|
||||
import me.shedaniel.rei.api.common.entry.EntryStack
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.render.DiffuseLighting
|
||||
import net.minecraft.client.render.LightmapTextureManager
|
||||
import net.minecraft.client.render.OverlayTexture
|
||||
import net.minecraft.client.render.VertexConsumerProvider
|
||||
import net.minecraft.client.render.model.BakedModel
|
||||
import net.minecraft.client.render.model.json.ModelTransformationMode
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.tooltip.TooltipType
|
||||
import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
|
||||
|
||||
object NEUItemEntryRenderer : EntryRenderer<SBItemStack>, BatchedEntryRenderer<SBItemStack, BakedModel> {
|
||||
override fun render(
|
||||
entry: EntryStack<SBItemStack>,
|
||||
context: DrawContext,
|
||||
bounds: Rectangle,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
delta: Float
|
||||
) {
|
||||
entry.asItemEntry().render(context, bounds, mouseX, mouseY, delta)
|
||||
}
|
||||
|
||||
val minecraft = MinecraftClient.getInstance()
|
||||
|
||||
override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
|
||||
val stack = entry.value.asImmutableItemStack()
|
||||
val lore = stack.getTooltip(
|
||||
Item.TooltipContext.DEFAULT,
|
||||
null,
|
||||
TooltipType.BASIC
|
||||
)
|
||||
return Tooltip.create(lore)
|
||||
}
|
||||
|
||||
override fun getExtraData(entry: EntryStack<SBItemStack>): BakedModel {
|
||||
return minecraft.itemRenderer.getModel(entry.asItemEntry().value, minecraft.world, minecraft.player, 0)
|
||||
}
|
||||
|
||||
override fun getBatchIdentifier(entry: EntryStack<SBItemStack>?, bounds: Rectangle?, extraData: BakedModel): Int {
|
||||
return 1738923 + if (extraData.isSideLit) 1 else 0
|
||||
}
|
||||
|
||||
override fun startBatch(
|
||||
entry: EntryStack<SBItemStack>,
|
||||
model: BakedModel,
|
||||
graphics: DrawContext,
|
||||
delta: Float
|
||||
) {
|
||||
val modelViewStack = RenderSystem.getModelViewStack()
|
||||
modelViewStack.pushMatrix()
|
||||
modelViewStack.scale(20.0f, 20.0f, 1.0f)
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
setupGL(model)
|
||||
}
|
||||
|
||||
fun setupGL(model: BakedModel) {
|
||||
minecraft.textureManager.getTexture(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
|
||||
.setFilter(false, false)
|
||||
RenderSystem.setShaderTexture(0, SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
|
||||
RenderSystem.enableBlend()
|
||||
RenderSystem.blendFunc(SrcFactor.SRC_ALPHA, DstFactor.ONE_MINUS_SRC_ALPHA)
|
||||
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f)
|
||||
val sideLit = model.isSideLit
|
||||
if (!sideLit) {
|
||||
DiffuseLighting.disableGuiDepthLighting()
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderBase(
|
||||
entry: EntryStack<SBItemStack>,
|
||||
model: BakedModel,
|
||||
graphics: DrawContext,
|
||||
immediate: VertexConsumerProvider.Immediate,
|
||||
bounds: Rectangle,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
delta: Float
|
||||
) {
|
||||
if (entry.isEmpty) return
|
||||
val value = entry.asItemEntry().value
|
||||
graphics.matrices.push()
|
||||
graphics.matrices.translate(bounds.centerX.toFloat() / 20.0f, bounds.centerY.toFloat() / 20.0f, 0.0f)
|
||||
graphics.matrices.scale(
|
||||
bounds.getWidth().toFloat() / 20.0f,
|
||||
-(bounds.getWidth() + bounds.getHeight()).toFloat() / 2.0f / 20.0f,
|
||||
1.0f
|
||||
)
|
||||
minecraft
|
||||
.itemRenderer
|
||||
.renderItem(
|
||||
value,
|
||||
ModelTransformationMode.GUI,
|
||||
false,
|
||||
graphics.matrices,
|
||||
immediate,
|
||||
LightmapTextureManager.MAX_LIGHT_COORDINATE,
|
||||
OverlayTexture.DEFAULT_UV,
|
||||
model
|
||||
)
|
||||
graphics.matrices.pop()
|
||||
|
||||
}
|
||||
|
||||
override fun afterBase(
|
||||
entry: EntryStack<SBItemStack>,
|
||||
model: BakedModel,
|
||||
graphics: DrawContext,
|
||||
delta: Float
|
||||
) {
|
||||
RenderSystem.getModelViewStack().popMatrix()
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
this.endGL(model)
|
||||
}
|
||||
|
||||
fun endGL(model: BakedModel) {
|
||||
RenderSystem.enableDepthTest()
|
||||
val sideLit = model.isSideLit
|
||||
if (!sideLit) {
|
||||
DiffuseLighting.enableGuiDepthLighting()
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderOverlay(
|
||||
entry: EntryStack<SBItemStack>,
|
||||
extraData: BakedModel,
|
||||
graphics: DrawContext,
|
||||
immediate: VertexConsumerProvider.Immediate,
|
||||
bounds: Rectangle,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
delta: Float
|
||||
) {
|
||||
val modelViewStack = RenderSystem.getModelViewStack()
|
||||
modelViewStack.pushMatrix()
|
||||
modelViewStack.mul(graphics.matrices.peek().positionMatrix)
|
||||
modelViewStack.translate(bounds.x.toFloat(), bounds.y.toFloat(), 0.0f)
|
||||
modelViewStack.scale(
|
||||
bounds.width.toFloat() / 16.0f,
|
||||
-(bounds.getWidth() + bounds.getHeight()).toFloat() / 2.0f / 16.0f,
|
||||
1.0f
|
||||
)
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
renderOverlay(DrawContext(minecraft, graphics.vertexConsumers), entry.asItemEntry())
|
||||
modelViewStack.popMatrix()
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
}
|
||||
|
||||
fun renderOverlay(graphics: DrawContext, entry: EntryStack<ItemStack>) {
|
||||
if (!entry.isEmpty) {
|
||||
graphics.drawItemInSlot(MinecraftClient.getInstance().textRenderer, entry.value, 0, 0, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun endBatch(
|
||||
entry: EntryStack<SBItemStack>?,
|
||||
extraData: BakedModel?,
|
||||
graphics: DrawContext?,
|
||||
delta: Float
|
||||
) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.rei
|
||||
|
||||
import me.shedaniel.rei.api.common.entry.EntrySerializer
|
||||
import me.shedaniel.rei.api.common.entry.EntryStack
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
|
||||
object NEUItemEntrySerializer : EntrySerializer<SBItemStack> {
|
||||
const val SKYBLOCK_ID_ENTRY = "SKYBLOCK_ID"
|
||||
const val SKYBLOCK_ITEM_COUNT = "SKYBLOCK_ITEM_COUNT"
|
||||
|
||||
override fun supportSaving(): Boolean = true
|
||||
override fun supportReading(): Boolean = true
|
||||
|
||||
override fun read(tag: NbtCompound): SBItemStack {
|
||||
val id = SkyblockId(tag.getString(SKYBLOCK_ID_ENTRY))
|
||||
val count = if (tag.contains(SKYBLOCK_ITEM_COUNT)) tag.getInt(SKYBLOCK_ITEM_COUNT) else 1
|
||||
return SBItemStack(id, count)
|
||||
}
|
||||
|
||||
override fun save(entry: EntryStack<SBItemStack>, value: SBItemStack): NbtCompound {
|
||||
return NbtCompound().apply {
|
||||
putString(SKYBLOCK_ID_ENTRY, value.skyblockId.neuItem)
|
||||
putInt(SKYBLOCK_ITEM_COUNT, value.getStackSize())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) }
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.rei
|
||||
|
||||
import io.github.moulberry.repo.data.NEUCraftingRecipe
|
||||
import io.github.moulberry.repo.data.NEUForgeRecipe
|
||||
import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
|
||||
import io.github.moulberry.repo.data.NEUMobDropRecipe
|
||||
import io.github.moulberry.repo.data.NEURecipe
|
||||
import java.util.Optional
|
||||
import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator
|
||||
import me.shedaniel.rei.api.client.view.ViewSearchBuilder
|
||||
import me.shedaniel.rei.api.common.display.Display
|
||||
import me.shedaniel.rei.api.common.entry.EntryStack
|
||||
import moe.nea.firmament.rei.recipes.SBCraftingRecipe
|
||||
import moe.nea.firmament.rei.recipes.SBEssenceUpgradeRecipe
|
||||
import moe.nea.firmament.rei.recipes.SBForgeRecipe
|
||||
import moe.nea.firmament.rei.recipes.SBKatRecipe
|
||||
import moe.nea.firmament.rei.recipes.SBMobDropRecipe
|
||||
import moe.nea.firmament.repo.EssenceRecipeProvider
|
||||
import moe.nea.firmament.repo.RepoManager
|
||||
|
||||
|
||||
val SkyblockCraftingRecipeDynamicGenerator =
|
||||
neuDisplayGenerator<SBCraftingRecipe, NEUCraftingRecipe> { SBCraftingRecipe(it) }
|
||||
|
||||
val SkyblockForgeRecipeDynamicGenerator =
|
||||
neuDisplayGenerator<SBForgeRecipe, NEUForgeRecipe> { SBForgeRecipe(it) }
|
||||
|
||||
val SkyblockMobDropRecipeDynamicGenerator =
|
||||
neuDisplayGenerator<SBMobDropRecipe, NEUMobDropRecipe> { SBMobDropRecipe(it) }
|
||||
|
||||
val SkyblockKatRecipeDynamicGenerator =
|
||||
neuDisplayGenerator<SBKatRecipe, NEUKatUpgradeRecipe> { SBKatRecipe(it) }
|
||||
val SkyblockEssenceRecipeDynamicGenerator =
|
||||
neuDisplayGenerator<SBEssenceUpgradeRecipe, EssenceRecipeProvider.EssenceUpgradeRecipe> { SBEssenceUpgradeRecipe(it) }
|
||||
|
||||
inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(crossinline mapper: (T) -> D) =
|
||||
object : DynamicDisplayGenerator<D> {
|
||||
override fun getRecipeFor(entry: EntryStack<*>): Optional<List<D>> {
|
||||
if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
|
||||
val item = entry.castValue<SBItemStack>()
|
||||
val recipes = RepoManager.getRecipesFor(item.skyblockId)
|
||||
val craftingRecipes = recipes.filterIsInstance<T>()
|
||||
return Optional.of(craftingRecipes.map(mapper))
|
||||
}
|
||||
|
||||
override fun generate(builder: ViewSearchBuilder): Optional<List<D>> {
|
||||
if (SBCraftingRecipe.Category.catIdentifier !in builder.categories) return Optional.empty()
|
||||
return Optional.of(
|
||||
RepoManager.getAllRecipes().filterIsInstance<T>().map { mapper(it) }
|
||||
.toList()
|
||||
)
|
||||
}
|
||||
|
||||
override fun getUsageFor(entry: EntryStack<*>): Optional<List<D>> {
|
||||
if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
|
||||
val item = entry.castValue<SBItemStack>()
|
||||
val recipes = RepoManager.getUsagesFor(item.skyblockId)
|
||||
val craftingRecipes = recipes.filterIsInstance<T>()
|
||||
return Optional.of(craftingRecipes.map(mapper))
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.rei
|
||||
|
||||
import dev.architectury.event.CompoundEventResult
|
||||
import me.shedaniel.math.Point
|
||||
import me.shedaniel.rei.api.client.registry.screen.FocusedStackProvider
|
||||
import me.shedaniel.rei.api.common.entry.EntryStack
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
|
||||
import moe.nea.firmament.util.skyBlockId
|
||||
|
||||
object SkyblockItemIdFocusedStackProvider : FocusedStackProvider {
|
||||
override fun provide(screen: Screen?, mouse: Point?): CompoundEventResult<EntryStack<*>> {
|
||||
if (screen !is HandledScreen<*>) return CompoundEventResult.pass()
|
||||
screen as AccessorHandledScreen
|
||||
val focusedSlot = screen.focusedSlot_Firmament ?: return CompoundEventResult.pass()
|
||||
val item = focusedSlot.stack ?: return CompoundEventResult.pass()
|
||||
val skyblockId = item.skyBlockId ?: return CompoundEventResult.pass()
|
||||
return CompoundEventResult.interruptTrue(SBItemEntryDefinition.getEntry(skyblockId))
|
||||
}
|
||||
|
||||
override fun getPriority(): Double = 1_000_000.0
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.rei
|
||||
|
||||
import me.shedaniel.math.Point
|
||||
|
||||
operator fun Point.plus(other: Point): Point = Point(
|
||||
this.x + other.x,
|
||||
this.y + other.y,
|
||||
)
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.rei.recipes
|
||||
|
||||
import io.github.moulberry.repo.data.NEUCraftingRecipe
|
||||
import io.github.moulberry.repo.data.NEUIngredient
|
||||
import me.shedaniel.math.Point
|
||||
import me.shedaniel.math.Rectangle
|
||||
import me.shedaniel.rei.api.client.gui.Renderer
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widget
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widgets
|
||||
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
|
||||
import me.shedaniel.rei.api.common.category.CategoryIdentifier
|
||||
import me.shedaniel.rei.api.common.util.EntryStacks
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.rei.SBItemEntryDefinition
|
||||
|
||||
class SBCraftingRecipe(override val neuRecipe: NEUCraftingRecipe) : SBRecipe() {
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier
|
||||
|
||||
object Category : DisplayCategory<SBCraftingRecipe> {
|
||||
val catIdentifier = CategoryIdentifier.of<SBCraftingRecipe>(Firmament.MOD_ID, "crafing_recipe")
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<out SBCraftingRecipe> = catIdentifier
|
||||
|
||||
override fun getTitle(): Text = Text.literal("SkyBlock Crafting")
|
||||
|
||||
override fun getIcon(): Renderer = EntryStacks.of(Blocks.CRAFTING_TABLE)
|
||||
override fun setupDisplay(display: SBCraftingRecipe, bounds: Rectangle): List<Widget> {
|
||||
val point = Point(bounds.centerX - 58, bounds.centerY - 27)
|
||||
return buildList {
|
||||
add(Widgets.createRecipeBase(bounds))
|
||||
add(Widgets.createArrow(Point(point.x + 60, point.y + 18)))
|
||||
add(Widgets.createResultSlotBackground(Point(point.x + 95, point.y + 19)))
|
||||
for (i in 0 until 3) {
|
||||
for (j in 0 until 3) {
|
||||
val slot = Widgets.createSlot(Point(point.x + 1 + i * 18, point.y + 1 + j * 18)).markInput()
|
||||
add(slot)
|
||||
val item = display.neuRecipe.inputs[i + j * 3]
|
||||
if (item == NEUIngredient.SENTINEL_EMPTY) continue
|
||||
slot.entry(SBItemEntryDefinition.getEntry(item)) // TODO: make use of stackable item entries
|
||||
}
|
||||
}
|
||||
add(
|
||||
Widgets.createSlot(Point(point.x + 95, point.y + 19))
|
||||
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.output))
|
||||
.disableBackground().markOutput()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
|
||||
package moe.nea.firmament.rei.recipes
|
||||
|
||||
import me.shedaniel.math.Point
|
||||
import me.shedaniel.math.Rectangle
|
||||
import me.shedaniel.rei.api.client.gui.Renderer
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widget
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widgets
|
||||
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
|
||||
import me.shedaniel.rei.api.common.category.CategoryIdentifier
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.rei.SBItemEntryDefinition
|
||||
import moe.nea.firmament.rei.SBItemStack
|
||||
import moe.nea.firmament.repo.EssenceRecipeProvider
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
|
||||
class SBEssenceUpgradeRecipe(override val neuRecipe: EssenceRecipeProvider.EssenceUpgradeRecipe) : SBRecipe() {
|
||||
object Category : DisplayCategory<SBEssenceUpgradeRecipe> {
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<SBEssenceUpgradeRecipe> =
|
||||
CategoryIdentifier.of(Firmament.MOD_ID, "essence_upgrade")
|
||||
|
||||
override fun getTitle(): Text {
|
||||
return Text.literal("Essence Upgrades")
|
||||
}
|
||||
|
||||
override fun getIcon(): Renderer {
|
||||
return SBItemEntryDefinition.getEntry(SkyblockId("ESSENCE_WITHER"))
|
||||
}
|
||||
|
||||
override fun setupDisplay(display: SBEssenceUpgradeRecipe, bounds: Rectangle): List<Widget> {
|
||||
val recipe = display.neuRecipe
|
||||
val list = mutableListOf<Widget>()
|
||||
list.add(Widgets.createRecipeBase(bounds))
|
||||
list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 - 18 / 2))
|
||||
.markInput()
|
||||
.entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter - 1))))
|
||||
list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 + 18 / 2))
|
||||
.markInput()
|
||||
.entry(SBItemEntryDefinition.getEntry(recipe.essenceIngredient)))
|
||||
list.add(Widgets.createSlot(Point(bounds.maxX - 12 - 16, bounds.centerY - 8))
|
||||
.markOutput()
|
||||
.entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter))))
|
||||
val extraItems = recipe.extraItems
|
||||
list.add(Widgets.createArrow(Point(bounds.centerX - 24 / 2,
|
||||
if (extraItems.isEmpty()) bounds.centerY - 17 / 2
|
||||
else bounds.centerY + 18 / 2)))
|
||||
for ((index, item) in extraItems.withIndex()) {
|
||||
list.add(Widgets.createSlot(
|
||||
Point(bounds.centerX - extraItems.size * 16 / 2 - 2 / 2 + index * 18,
|
||||
bounds.centerY - 18 / 2))
|
||||
.markInput()
|
||||
.entry(SBItemEntryDefinition.getEntry(item)))
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<*> {
|
||||
return Category.categoryIdentifier
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.rei.recipes
|
||||
|
||||
import io.github.moulberry.repo.data.NEUForgeRecipe
|
||||
import me.shedaniel.math.Point
|
||||
import me.shedaniel.math.Rectangle
|
||||
import me.shedaniel.rei.api.client.gui.Renderer
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widget
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widgets
|
||||
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
|
||||
import me.shedaniel.rei.api.common.category.CategoryIdentifier
|
||||
import me.shedaniel.rei.api.common.util.EntryStacks
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.rei.SBItemEntryDefinition
|
||||
import moe.nea.firmament.rei.plus
|
||||
|
||||
class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
|
||||
|
||||
object Category : DisplayCategory<SBForgeRecipe> {
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<SBForgeRecipe> =
|
||||
CategoryIdentifier.of(Firmament.MOD_ID, "forge_recipe")
|
||||
|
||||
override fun getTitle(): Text = Text.literal("Forge Recipes")
|
||||
override fun getDisplayHeight(): Int {
|
||||
return 104
|
||||
}
|
||||
|
||||
override fun getIcon(): Renderer = EntryStacks.of(Blocks.ANVIL)
|
||||
override fun setupDisplay(display: SBForgeRecipe, bounds: Rectangle): List<Widget> {
|
||||
return buildList {
|
||||
add(Widgets.createRecipeBase(bounds))
|
||||
add(Widgets.createResultSlotBackground(Point(bounds.minX + 124, bounds.minY + 46)))
|
||||
val arrow = Widgets.createArrow(Point(bounds.minX + 90, bounds.minY + 54 - 18 / 2))
|
||||
add(arrow)
|
||||
add(Widgets.createTooltip(arrow.bounds, Text.stringifiedTranslatable("firmament.recipe.forge.time", display.neuRecipe.duration.seconds)))
|
||||
val ingredientsCenter = Point(bounds.minX + 49 - 8, bounds.minY + 54 - 8)
|
||||
val count = display.neuRecipe.inputs.size
|
||||
if (count == 1) {
|
||||
add(
|
||||
Widgets.createSlot(Point(ingredientsCenter.x, ingredientsCenter.y)).markInput()
|
||||
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.inputs.single()))
|
||||
)
|
||||
} else {
|
||||
display.neuRecipe.inputs.forEachIndexed { idx, ingredient ->
|
||||
val rad = Math.PI * 2 * idx / count
|
||||
add(
|
||||
Widgets.createSlot(
|
||||
Point(
|
||||
cos(rad) * 30,
|
||||
sin(rad) * 30,
|
||||
) + ingredientsCenter
|
||||
).markInput().entry(SBItemEntryDefinition.getEntry(ingredient))
|
||||
)
|
||||
}
|
||||
}
|
||||
add(
|
||||
Widgets.createSlot(Point(bounds.minX + 124, bounds.minY + 46)).markOutput().disableBackground()
|
||||
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.outputStack))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
|
||||
package moe.nea.firmament.rei.recipes
|
||||
|
||||
import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
|
||||
import io.github.notenoughupdates.moulconfig.common.IMinecraft
|
||||
import io.github.notenoughupdates.moulconfig.gui.GuiComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
|
||||
import io.github.notenoughupdates.moulconfig.gui.MouseEvent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.SliderComponent
|
||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||
import io.github.notenoughupdates.moulconfig.observer.Property
|
||||
import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
|
||||
import me.shedaniel.math.Point
|
||||
import me.shedaniel.math.Rectangle
|
||||
import me.shedaniel.rei.api.client.gui.Renderer
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widget
|
||||
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widgets
|
||||
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
|
||||
import me.shedaniel.rei.api.common.category.CategoryIdentifier
|
||||
import me.shedaniel.rei.api.common.util.EntryStacks
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.Element
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.rei.PetData
|
||||
import moe.nea.firmament.rei.SBItemEntryDefinition
|
||||
import moe.nea.firmament.rei.SBItemStack
|
||||
import moe.nea.firmament.util.FirmFormatters
|
||||
import moe.nea.firmament.util.MC
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
|
||||
class SBKatRecipe(override val neuRecipe: NEUKatUpgradeRecipe) : SBRecipe() {
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
|
||||
|
||||
object Category : DisplayCategory<SBKatRecipe> {
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<SBKatRecipe> =
|
||||
CategoryIdentifier.of(Firmament.MOD_ID, "kat_recipe")
|
||||
|
||||
override fun getTitle(): Text = Text.literal("Kat Pet Upgrade")
|
||||
override fun getDisplayHeight(): Int {
|
||||
return 100
|
||||
}
|
||||
|
||||
override fun getIcon(): Renderer = EntryStacks.of(Items.BONE)
|
||||
override fun setupDisplay(display: SBKatRecipe, bounds: Rectangle): List<Widget> {
|
||||
return buildList {
|
||||
val arrowWidth = 24
|
||||
val recipe = display.neuRecipe
|
||||
val levelValue = Property.upgrade(GetSetter.floating(0F))
|
||||
val slider = SliderComponent(levelValue, 1F, 100F, 1f, 100)
|
||||
val outputStack = SBItemStack(SkyblockId(recipe.output.itemId))
|
||||
val inputStack = SBItemStack(SkyblockId(recipe.input.itemId))
|
||||
val inputLevelLabelCenter = Point(bounds.minX + 30 - 18 + 5 + 8, bounds.minY + 25)
|
||||
val inputLevelLabel = Widgets.createLabel(
|
||||
inputLevelLabelCenter,
|
||||
Text.literal("")).centered()
|
||||
val outputLevelLabelCenter = Point(bounds.maxX - 30 + 8, bounds.minY + 25)
|
||||
val outputLevelLabel = Widgets.createLabel(
|
||||
outputLevelLabelCenter,
|
||||
Text.literal("")).centered()
|
||||
val coinStack = SBItemStack(SkyblockId.COINS, recipe.coins.toInt())
|
||||
levelValue.whenChanged { oldValue, newValue ->
|
||||
if (oldValue.toInt() == newValue.toInt()) return@whenChanged
|
||||
val oldInput = inputStack.getPetData() ?: return@whenChanged
|
||||
val newInput = PetData.forLevel(oldInput.petId, oldInput.rarity, newValue.toInt())
|
||||
inputStack.setPetData(newInput)
|
||||
val oldOutput = outputStack.getPetData() ?: return@whenChanged
|
||||
val newOutput = PetData(oldOutput.rarity, oldOutput.petId, newInput.exp)
|
||||
outputStack.setPetData(newOutput)
|
||||
inputLevelLabel.message = Text.literal(newInput.levelData.currentLevel.toString())
|
||||
inputLevelLabel.bounds.location = Point(
|
||||
inputLevelLabelCenter.x - MC.font.getWidth(inputLevelLabel.message) / 2,
|
||||
inputLevelLabelCenter.y)
|
||||
outputLevelLabel.message = Text.literal(newOutput.levelData.currentLevel.toString())
|
||||
outputLevelLabel.bounds.location = Point(
|
||||
outputLevelLabelCenter.x - MC.font.getWidth(outputLevelLabel.message) / 2,
|
||||
outputLevelLabelCenter.y)
|
||||
coinStack.setStackSize((recipe.coins * (1 - 0.3 * newValue / 100)).toInt())
|
||||
}
|
||||
levelValue.set(1F)
|
||||
add(Widgets.createRecipeBase(bounds))
|
||||
add(wrapWidget(Rectangle(bounds.centerX - slider.width / 2,
|
||||
bounds.maxY - 30,
|
||||
slider.width,
|
||||
slider.height),
|
||||
slider))
|
||||
add(Widgets.withTooltip(
|
||||
Widgets.createArrow(Point(bounds.centerX - arrowWidth / 2, bounds.minY + 40)),
|
||||
Text.literal("Upgrade time: " + FirmFormatters.formatTimespan(recipe.seconds.seconds))))
|
||||
|
||||
add(Widgets.createResultSlotBackground(Point(bounds.maxX - 30, bounds.minY + 40)))
|
||||
add(inputLevelLabel)
|
||||
add(outputLevelLabel)
|
||||
add(Widgets.createSlot(Point(bounds.maxX - 30, bounds.minY + 40)).markOutput().disableBackground()
|
||||
.entry(SBItemEntryDefinition.getEntry(outputStack)))
|
||||
add(Widgets.createSlot(Point(bounds.minX + 30 - 18 + 5, bounds.minY + 40)).markInput()
|
||||
.entry(SBItemEntryDefinition.getEntry(inputStack)))
|
||||
|
||||
val allInputs = recipe.items.map { SBItemEntryDefinition.getEntry(it) } +
|
||||
listOf(SBItemEntryDefinition.getEntry(coinStack))
|
||||
for ((index, item) in allInputs.withIndex()) {
|
||||
add(Widgets.createSlot(
|
||||
Point(bounds.centerX + index * 20 - allInputs.size * 18 / 2 - (allInputs.size - 1) * 2 / 2,
|
||||
bounds.minY + 20))
|
||||
.markInput()
|
||||
.entry(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun wrapWidget(bounds: Rectangle, component: GuiComponent): Widget {
|
||||
return object : WidgetWithBounds() {
|
||||
override fun getBounds(): Rectangle {
|
||||
return bounds
|
||||
}
|
||||
|
||||
override fun children(): List<Element> {
|
||||
return listOf()
|
||||
}
|
||||
|
||||
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
context.matrices.push()
|
||||
context.matrices.translate(bounds.minX.toFloat(), bounds.minY.toFloat(), 0F)
|
||||
component.render(
|
||||
GuiImmediateContext(
|
||||
ModernRenderContext(context),
|
||||
bounds.minX, bounds.minY,
|
||||
bounds.width, bounds.height,
|
||||
mouseX - bounds.minX, mouseY - bounds.minY,
|
||||
mouseX, mouseY,
|
||||
mouseX.toFloat(), mouseY.toFloat()
|
||||
))
|
||||
context.matrices.pop()
|
||||
}
|
||||
|
||||
override fun mouseMoved(mouseX: Double, mouseY: Double) {
|
||||
val mouseXInt = mouseX.toInt()
|
||||
val mouseYInt = mouseY.toInt()
|
||||
component.mouseEvent(MouseEvent.Move(0F, 0F),
|
||||
GuiImmediateContext(
|
||||
IMinecraft.instance.provideTopLevelRenderContext(),
|
||||
bounds.minX, bounds.minY,
|
||||
bounds.width, bounds.height,
|
||||
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
|
||||
mouseXInt, mouseYInt,
|
||||
mouseX.toFloat(), mouseY.toFloat()
|
||||
))
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
val mouseXInt = mouseX.toInt()
|
||||
val mouseYInt = mouseY.toInt()
|
||||
return component.mouseEvent(MouseEvent.Click(button, true),
|
||||
GuiImmediateContext(
|
||||
IMinecraft.instance.provideTopLevelRenderContext(),
|
||||
bounds.minX, bounds.minY,
|
||||
bounds.width, bounds.height,
|
||||
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
|
||||
mouseXInt, mouseYInt,
|
||||
mouseX.toFloat(), mouseY.toFloat()
|
||||
))
|
||||
}
|
||||
|
||||
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
val mouseXInt = mouseX.toInt()
|
||||
val mouseYInt = mouseY.toInt()
|
||||
return component.mouseEvent(MouseEvent.Click(button, false),
|
||||
GuiImmediateContext(
|
||||
IMinecraft.instance.provideTopLevelRenderContext(),
|
||||
bounds.minX, bounds.minY,
|
||||
bounds.width, bounds.height,
|
||||
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
|
||||
mouseXInt, mouseYInt,
|
||||
mouseX.toFloat(), mouseY.toFloat()
|
||||
))
|
||||
}
|
||||
|
||||
override fun mouseDragged(
|
||||
mouseX: Double,
|
||||
mouseY: Double,
|
||||
button: Int,
|
||||
deltaX: Double,
|
||||
deltaY: Double
|
||||
): Boolean {
|
||||
val mouseXInt = mouseX.toInt()
|
||||
val mouseYInt = mouseY.toInt()
|
||||
return component.mouseEvent(MouseEvent.Move(deltaX.toFloat(), deltaY.toFloat()),
|
||||
GuiImmediateContext(
|
||||
IMinecraft.instance.provideTopLevelRenderContext(),
|
||||
bounds.minX, bounds.minY,
|
||||
bounds.width, bounds.height,
|
||||
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
|
||||
mouseXInt, mouseYInt,
|
||||
mouseX.toFloat(), mouseY.toFloat()
|
||||
))
|
||||
|
||||
}
|
||||
|
||||
override fun mouseScrolled(
|
||||
mouseX: Double,
|
||||
mouseY: Double,
|
||||
horizontalAmount: Double,
|
||||
verticalAmount: Double
|
||||
): Boolean {
|
||||
val mouseXInt = mouseX.toInt()
|
||||
val mouseYInt = mouseY.toInt()
|
||||
return component.mouseEvent(MouseEvent.Scroll(verticalAmount.toFloat()),
|
||||
GuiImmediateContext(
|
||||
IMinecraft.instance.provideTopLevelRenderContext(),
|
||||
bounds.minX, bounds.minY,
|
||||
bounds.width, bounds.height,
|
||||
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
|
||||
mouseXInt, mouseYInt,
|
||||
mouseX.toFloat(), mouseY.toFloat()
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
|
||||
package moe.nea.firmament.rei.recipes
|
||||
|
||||
import io.github.moulberry.repo.data.NEUMobDropRecipe
|
||||
import me.shedaniel.math.Point
|
||||
import me.shedaniel.math.Rectangle
|
||||
import me.shedaniel.rei.api.client.gui.Renderer
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widget
|
||||
import me.shedaniel.rei.api.client.gui.widgets.Widgets
|
||||
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
|
||||
import me.shedaniel.rei.api.common.category.CategoryIdentifier
|
||||
import me.shedaniel.rei.api.common.util.EntryStacks
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.gui.entity.EntityRenderer
|
||||
import moe.nea.firmament.gui.entity.EntityWidget
|
||||
import moe.nea.firmament.rei.SBItemEntryDefinition
|
||||
|
||||
class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
|
||||
|
||||
object Category : DisplayCategory<SBMobDropRecipe> {
|
||||
override fun getCategoryIdentifier(): CategoryIdentifier<SBMobDropRecipe> =
|
||||
CategoryIdentifier.of(Firmament.MOD_ID, "mob_drop_recipe")
|
||||
|
||||
override fun getTitle(): Text = Text.literal("Mob Drops")
|
||||
override fun getDisplayHeight(): Int {
|
||||
return 100
|
||||
}
|
||||
|
||||
override fun getIcon(): Renderer = EntryStacks.of(Items.DIAMOND_SWORD)
|
||||
override fun setupDisplay(display: SBMobDropRecipe, bounds: Rectangle): List<Widget> {
|
||||
return buildList {
|
||||
add(Widgets.createRecipeBase(bounds))
|
||||
val source = display.neuRecipe.render
|
||||
val entity = if (source.startsWith("@")) {
|
||||
EntityRenderer.constructEntity(Identifier.of(source.substring(1)))
|
||||
} else {
|
||||
EntityRenderer.applyModifiers(source, listOf())
|
||||
}
|
||||
if (entity != null) {
|
||||
val level = display.neuRecipe.level
|
||||
val fullMobName =
|
||||
if (level > 0) Text.translatable("firmament.recipe.mobs.name", level, display.neuRecipe.name)
|
||||
else Text.translatable("firmament.recipe.mobs.name.nolevel", display.neuRecipe.name)
|
||||
val tt = mutableListOf<Text>()
|
||||
tt.add((fullMobName))
|
||||
tt.add(Text.literal(""))
|
||||
if (display.neuRecipe.coins > 0) {
|
||||
tt.add(Text.stringifiedTranslatable("firmament.recipe.mobs.coins", display.neuRecipe.coins))
|
||||
}
|
||||
if (display.neuRecipe.combatExperience > 0) {
|
||||
tt.add(
|
||||
Text.stringifiedTranslatable(
|
||||
"firmament.recipe.mobs.combat",
|
||||
display.neuRecipe.combatExperience
|
||||
)
|
||||
)
|
||||
}
|
||||
if (display.neuRecipe.enchantingExperience > 0) {
|
||||
tt.add(
|
||||
Text.stringifiedTranslatable(
|
||||
"firmament.recipe.mobs.exp",
|
||||
display.neuRecipe.enchantingExperience
|
||||
)
|
||||
)
|
||||
}
|
||||
if (display.neuRecipe.extra != null)
|
||||
display.neuRecipe.extra.mapTo(tt) { Text.literal(it) }
|
||||
if (tt.size == 2)
|
||||
tt.removeAt(1)
|
||||
add(
|
||||
Widgets.withTooltip(
|
||||
EntityWidget(entity, Point(bounds.minX + 5, bounds.minY + 15)),
|
||||
tt
|
||||
)
|
||||
)
|
||||
}
|
||||
add(
|
||||
Widgets.createLabel(Point(bounds.minX + 15, bounds.minY + 5), Text.literal(display.neuRecipe.name))
|
||||
.leftAligned()
|
||||
)
|
||||
var x = bounds.minX + 60
|
||||
var y = bounds.minY + 20
|
||||
for (drop in display.neuRecipe.drops) {
|
||||
val lore = drop.extra.mapTo(mutableListOf()) { Text.literal(it) }
|
||||
if (drop.chance != null) {
|
||||
lore += listOf(Text.translatable("firmament.recipe.mobs.drops", drop.chance))
|
||||
}
|
||||
val item = SBItemEntryDefinition.getEntry(drop.dropItem)
|
||||
.value.copy(extraLore = lore)
|
||||
add(
|
||||
Widgets.createSlot(Point(x, y)).markOutput()
|
||||
.entries(listOf(SBItemEntryDefinition.getEntry(item)))
|
||||
)
|
||||
x += 18
|
||||
if (x > bounds.maxX - 30) {
|
||||
x = bounds.minX + 60
|
||||
y += 18
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.rei.recipes
|
||||
|
||||
import io.github.moulberry.repo.data.NEUIngredient
|
||||
import io.github.moulberry.repo.data.NEURecipe
|
||||
import me.shedaniel.rei.api.common.display.Display
|
||||
import me.shedaniel.rei.api.common.entry.EntryIngredient
|
||||
import moe.nea.firmament.rei.SBItemEntryDefinition
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
|
||||
abstract class SBRecipe : Display {
|
||||
abstract val neuRecipe: NEURecipe
|
||||
override fun getInputEntries(): List<EntryIngredient> {
|
||||
return neuRecipe.allInputs
|
||||
.filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
|
||||
.map {
|
||||
val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
|
||||
EntryIngredient.of(entryStack)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getOutputEntries(): List<EntryIngredient> {
|
||||
return neuRecipe.allOutputs
|
||||
.filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
|
||||
.map {
|
||||
val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
|
||||
EntryIngredient.of(entryStack)
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/main/kotlin/repo/PetData.kt
Normal file
24
src/main/kotlin/repo/PetData.kt
Normal 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) }
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
165
src/main/kotlin/repo/SBItemStack.kt
Normal file
165
src/main/kotlin/repo/SBItemStack.kt
Normal 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()
|
||||
}
|
||||
}
|
||||
@@ -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) }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user