diff options
Diffstat (limited to 'src/main/kotlin/features/inventory')
12 files changed, 271 insertions, 83 deletions
diff --git a/src/main/kotlin/features/inventory/PetFeatures.kt b/src/main/kotlin/features/inventory/PetFeatures.kt index 5ca10f7..bb39fbc 100644 --- a/src/main/kotlin/features/inventory/PetFeatures.kt +++ b/src/main/kotlin/features/inventory/PetFeatures.kt @@ -1,14 +1,24 @@ package moe.nea.firmament.features.inventory -import net.minecraft.util.Identifier +import moe.nea.jarvis.api.Point +import net.minecraft.item.ItemStack +import net.minecraft.text.Text +import net.minecraft.util.Formatting +import moe.nea.firmament.Firmament import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.HudRenderEvent import moe.nea.firmament.events.SlotRenderEvents import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.FirmFormatters.formatPercent +import moe.nea.firmament.util.FirmFormatters.shortFormat import moe.nea.firmament.util.MC import moe.nea.firmament.util.petData import moe.nea.firmament.util.render.drawGuiTexture +import moe.nea.firmament.util.skyblock.Rarity +import moe.nea.firmament.util.titleCase import moe.nea.firmament.util.useMatch +import moe.nea.firmament.util.withColor object PetFeatures : FirmamentFeature { override val identifier: String @@ -19,9 +29,12 @@ object PetFeatures : FirmamentFeature { object TConfig : ManagedConfig(identifier, Category.INVENTORY) { val highlightEquippedPet by toggle("highlight-pet") { true } + var petOverlay by toggle("pet-overlay") { false } + val petOverlayHud by position("pet-overlay-hud", 80, 10) { Point(0.5, 1.0) } } val petMenuTitle = "Pets(?: \\([0-9]+/[0-9]+\\))?".toPattern() + var petItemStack: ItemStack? = null @Subscribe fun onSlotRender(event: SlotRenderEvents.Before) { @@ -29,12 +42,44 @@ object PetFeatures : FirmamentFeature { val stack = event.slot.stack if (stack.petData?.active == true) petMenuTitle.useMatch(MC.screenName ?: return) { - event.context.drawGuiTexture( - event.slot.x, event.slot.y, 0, 16, 16, - Identifier.of("firmament:selected_pet_background") - ) - } + petItemStack = stack + event.context.drawGuiTexture( + Firmament.identifier("selected_pet_background"), + event.slot.x, event.slot.y, 16, 16, + ) + } } + @Subscribe + fun onRenderHud(it: HudRenderEvent) { + if (!TConfig.petOverlay) return + val itemStack = petItemStack ?: return + val petData = petItemStack?.petData ?: return + val rarity = Rarity.fromNeuRepo(petData.tier) + val rarityCode = Rarity.colourMap[rarity] ?: Formatting.WHITE + val xp = petData.level + val petType = titleCase(petData.type) + val heldItem = petData.heldItem?.let { item -> "Held Item: ${titleCase(item)}" } + + it.context.matrices.push() + TConfig.petOverlayHud.applyTransformations(it.context.matrices) + + val lines = mutableListOf<Text>() + it.context.matrices.push() + it.context.matrices.translate(-0.5, -0.5, 0.0) + it.context.matrices.scale(2f, 2f, 1f) + it.context.drawItem(itemStack, 0, 0) + it.context.matrices.pop() + lines.add(Text.literal("[Lvl ${xp.currentLevel}] ").append(Text.literal(petType).withColor(rarityCode))) + if (heldItem != null) lines.add(Text.literal(heldItem)) + if (xp.currentLevel != xp.maxLevel) lines.add(Text.literal("Required L${xp.currentLevel + 1}: ${shortFormat(xp.expInCurrentLevel.toDouble())}/${shortFormat(xp.expRequiredForNextLevel.toDouble())} (${formatPercent(xp.percentageToNextLevel.toDouble())})")) + lines.add(Text.literal("Required L100: ${shortFormat(xp.expTotal.toDouble())}/${shortFormat(xp.expRequiredForMaxLevel.toDouble())} (${formatPercent(xp.percentageToMaxLevel.toDouble())})")) + + for ((index, line) in lines.withIndex()) { + it.context.drawText(MC.font, line.copy().withColor(Formatting.GRAY), 36, MC.font.fontHeight * index, -1, true) + } + + it.context.matrices.pop() + } } diff --git a/src/main/kotlin/features/inventory/PriceData.kt b/src/main/kotlin/features/inventory/PriceData.kt index 4477203..a724d63 100644 --- a/src/main/kotlin/features/inventory/PriceData.kt +++ b/src/main/kotlin/features/inventory/PriceData.kt @@ -1,5 +1,3 @@ - - package moe.nea.firmament.features.inventory import net.minecraft.text.Text @@ -8,44 +6,68 @@ import moe.nea.firmament.events.ItemTooltipEvent import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.repo.HypixelStaticData -import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.FirmFormatters.formatCommas +import moe.nea.firmament.util.bold +import moe.nea.firmament.util.gold import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.yellow object PriceData : FirmamentFeature { - override val identifier: String - get() = "price-data" + override val identifier: String + get() = "price-data" + + object TConfig : ManagedConfig(identifier, Category.INVENTORY) { + val tooltipEnabled by toggle("enable-always") { true } + val enableKeybinding by keyBindingWithDefaultUnbound("enable-keybind") + } - object TConfig : ManagedConfig(identifier, Category.INVENTORY) { - val tooltipEnabled by toggle("enable-always") { true } - val enableKeybinding by keyBindingWithDefaultUnbound("enable-keybind") - } + override val config get() = TConfig - override val config get() = TConfig + fun formatPrice(label: Text, price: Double): Text { + return Text.literal("") + .yellow() + .bold() + .append(label) + .append(": ") + .append( + Text.literal(formatCommas(price, fractionalDigits = 1)) + .append(if(price != 1.0) " coins" else " coin") + .gold() + .bold() + ) + } - @Subscribe - fun onItemTooltip(it: ItemTooltipEvent) { - if (!TConfig.tooltipEnabled && !TConfig.enableKeybinding.isPressed()) { - return - } - val sbId = it.stack.skyBlockId - val bazaarData = HypixelStaticData.bazaarData[sbId] - val lowestBin = HypixelStaticData.lowestBin[sbId] - if (bazaarData != null) { - it.lines.add(Text.literal("")) - it.lines.add( - Text.stringifiedTranslatable("firmament.tooltip.bazaar.sell-order", - FirmFormatters.formatCommas(bazaarData.quickStatus.sellPrice, 1)) - ) - it.lines.add( - Text.stringifiedTranslatable("firmament.tooltip.bazaar.buy-order", - FirmFormatters.formatCommas(bazaarData.quickStatus.buyPrice, 1)) - ) - } else if (lowestBin != null) { - it.lines.add(Text.literal("")) - it.lines.add( - Text.stringifiedTranslatable("firmament.tooltip.ah.lowestbin", - FirmFormatters.formatCommas(lowestBin, 1)) - ) - } - } + @Subscribe + fun onItemTooltip(it: ItemTooltipEvent) { + if (!TConfig.tooltipEnabled && !TConfig.enableKeybinding.isPressed()) { + return + } + val sbId = it.stack.skyBlockId + val bazaarData = HypixelStaticData.bazaarData[sbId] + val lowestBin = HypixelStaticData.lowestBin[sbId] + if (bazaarData != null) { + it.lines.add(Text.literal("")) + it.lines.add( + formatPrice( + tr("firmament.tooltip.bazaar.sell-order", "Bazaar Sell Order"), + bazaarData.quickStatus.sellPrice + ) + ) + it.lines.add( + formatPrice( + tr("firmament.tooltip.bazaar.buy-order", "Bazaar Buy Order"), + bazaarData.quickStatus.buyPrice + ) + ) + } else if (lowestBin != null) { + it.lines.add(Text.literal("")) + it.lines.add( + formatPrice( + tr("firmament.tooltip.ah.lowestbin", "Lowest BIN"), + lowestBin + ) + ) + } + } } diff --git a/src/main/kotlin/features/inventory/REIDependencyWarner.kt b/src/main/kotlin/features/inventory/REIDependencyWarner.kt index 1e9b1b8..7d88dd1 100644 --- a/src/main/kotlin/features/inventory/REIDependencyWarner.kt +++ b/src/main/kotlin/features/inventory/REIDependencyWarner.kt @@ -1,5 +1,6 @@ package moe.nea.firmament.features.inventory +import java.net.URI import net.fabricmc.loader.api.FabricLoader import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -38,7 +39,7 @@ object REIDependencyWarner { .white() .append(Text.literal("[").aqua()) .append(Text.translatable("firmament.download", modName) - .styled { it.withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, modrinthLink(slug))) } + .styled { it.withClickEvent(ClickEvent.OpenUrl(URI (modrinthLink(slug)))) } .yellow() .also { if (alreadyDownloaded) diff --git a/src/main/kotlin/features/inventory/SlotLocking.kt b/src/main/kotlin/features/inventory/SlotLocking.kt index 7a3a152..d3348a2 100644 --- a/src/main/kotlin/features/inventory/SlotLocking.kt +++ b/src/main/kotlin/features/inventory/SlotLocking.kt @@ -4,10 +4,23 @@ package moe.nea.firmament.features.inventory import java.util.UUID import org.lwjgl.glfw.GLFW +import util.render.CustomRenderLayers +import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.JsonDecoder +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.int import kotlinx.serialization.serializer import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.client.render.RenderLayer +import net.minecraft.client.render.RenderLayers +import net.minecraft.client.render.TexturedRenderLayers import net.minecraft.entity.player.PlayerInventory import net.minecraft.screen.GenericContainerScreenHandler import net.minecraft.screen.slot.Slot @@ -36,7 +49,6 @@ import moe.nea.firmament.util.mc.ScreenUtil.getSlotByIndex import moe.nea.firmament.util.mc.SlotUtils.swapWithHotBar import moe.nea.firmament.util.mc.displayNameAccordingToNbt import moe.nea.firmament.util.mc.loreAccordingToNbt -import moe.nea.firmament.util.render.GuiRenderLayers import moe.nea.firmament.util.render.drawLine import moe.nea.firmament.util.skyblock.DungeonUtil import moe.nea.firmament.util.skyblockUUID @@ -51,9 +63,66 @@ object SlotLocking : FirmamentFeature { val lockedSlots: MutableSet<Int> = mutableSetOf(), val lockedSlotsRift: MutableSet<Int> = mutableSetOf(), val lockedUUIDs: MutableSet<UUID> = mutableSetOf(), - val boundSlots: MutableMap<Int, Int> = mutableMapOf() + val boundSlots: BoundSlots = BoundSlots() ) + @Serializable + data class BoundSlot( + val hotbar: Int, + val inventory: Int, + ) + + @Serializable(with = BoundSlots.Serializer::class) + data class BoundSlots( + val pairs: MutableSet<BoundSlot> = mutableSetOf() + ) { + fun findMatchingSlots(index: Int): List<BoundSlot> { + return pairs.filter { it.hotbar == index || it.inventory == index } + } + + fun removeDuplicateForInventory(index: Int) { + pairs.removeIf { it.inventory == index } + } + + fun removeAllInvolving(index: Int): Boolean { + return pairs.removeIf { it.inventory == index || it.hotbar == index } + } + + fun insert(hotbar: Int, inventory: Int) { + if (!TConfig.allowMultiBinding) { + removeAllInvolving(hotbar) + removeAllInvolving(inventory) + } + pairs.add(BoundSlot(hotbar, inventory)) + } + + object Serializer : KSerializer<BoundSlots> { + override val descriptor: SerialDescriptor + get() = serializer<JsonElement>().descriptor + + override fun serialize( + encoder: Encoder, + value: BoundSlots + ) { + serializer<MutableSet<BoundSlot>>() + .serialize(encoder, value.pairs) + } + + override fun deserialize(decoder: Decoder): BoundSlots { + decoder as JsonDecoder + val json = decoder.decodeJsonElement() + if (json is JsonObject) { + return BoundSlots(json.entries.map { + BoundSlot(it.key.toInt(), (it.value as JsonPrimitive).int) + }.toMutableSet()) + } + return BoundSlots(decoder.json.decodeFromJsonElement(serializer<MutableSet<BoundSlot>>(), json)) + + } + } + } + + object TConfig : ManagedConfig(identifier, Category.INVENTORY) { val lockSlot by keyBinding("lock") { GLFW.GLFW_KEY_L } val lockUUID by keyBindingWithOutDefaultModifiers("lock-uuid") { @@ -62,6 +131,7 @@ object SlotLocking : FirmamentFeature { val slotBind by keyBinding("bind") { GLFW.GLFW_KEY_L } val slotBindRequireShift by toggle("require-quick-move") { true } val slotRenderLines by choice("bind-render") { SlotRenderLinesMode.ONLY_BOXES } + val allowMultiBinding by toggle("multi-bind") { true } // TODO: filter based on this option val allowDroppingInDungeons by toggle("drop-in-dungeons") { true } } @@ -177,19 +247,19 @@ object SlotLocking : FirmamentFeature { @Subscribe fun onQuickMoveBoundSlot(it: IsSlotProtectedEvent) { - val boundSlots = DConfig.data?.boundSlots ?: mapOf() + val boundSlots = DConfig.data?.boundSlots ?: BoundSlots() val isValidAction = it.actionType == SlotActionType.QUICK_MOVE || (it.actionType == SlotActionType.PICKUP && !TConfig.slotBindRequireShift) if (!isValidAction) return val handler = MC.handledScreen?.screenHandler ?: return val slot = it.slot if (slot != null && it.slot.inventory is PlayerInventory) { - val boundSlot = boundSlots.entries.find { - it.value == slot.index || it.key == slot.index - } ?: return + val matchingSlots = boundSlots.findMatchingSlots(slot.index) + if (matchingSlots.isEmpty()) return it.protectSilent() - val inventorySlot = MC.handledScreen?.getSlotByIndex(boundSlot.value, true) - inventorySlot?.swapWithHotBar(handler, boundSlot.key) + val boundSlot = matchingSlots.singleOrNull() ?: return + val inventorySlot = MC.handledScreen?.getSlotByIndex(boundSlot.inventory, true) + inventorySlot?.swapWithHotBar(handler, boundSlot.hotbar) } } @@ -228,10 +298,8 @@ object SlotLocking : FirmamentFeature { val boundSlots = DConfig.data?.boundSlots ?: return lockedSlots?.remove(hotBarSlot.index) lockedSlots?.remove(invSlot.index) - boundSlots.entries.removeIf { - it.value == invSlot.index - } - boundSlots[hotBarSlot.index] = invSlot.index + boundSlots.removeDuplicateForInventory(invSlot.index) + boundSlots.insert(hotBarSlot.index, invSlot.index) DConfig.markDirty() CommonSoundEffects.playSuccess() return @@ -245,9 +313,7 @@ object SlotLocking : FirmamentFeature { storedLockingSlot = null val boundSlots = DConfig.data?.boundSlots ?: return if (slot != null) - boundSlots.entries.removeIf { - it.value == slot.index || it.key == slot.index - } + boundSlots.removeAllInvolving(slot.index) } } @@ -258,9 +324,10 @@ object SlotLocking : FirmamentFeature { val accScreen = event.screen as AccessorHandledScreen val sx = accScreen.x_Firmament val sy = accScreen.y_Firmament - for (it in boundSlots.entries) { - val hotbarSlot = findByIndex(it.key) ?: continue - val inventorySlot = findByIndex(it.value) ?: continue + val highlitSlots = mutableSetOf<Slot>() + for (it in boundSlots.pairs) { + val hotbarSlot = findByIndex(it.hotbar) ?: continue + val inventorySlot = findByIndex(it.inventory) ?: continue val (hotX, hotY) = hotbarSlot.lineCenter() val (invX, invY) = inventorySlot.lineCenter() @@ -268,22 +335,27 @@ object SlotLocking : FirmamentFeature { || accScreen.focusedSlot_Firmament === inventorySlot if (!anyHovered && TConfig.slotRenderLines == SlotRenderLinesMode.NOTHING) continue - val color = if (anyHovered) - me.shedaniel.math.Color.ofOpaque(0x00FF00) - else - me.shedaniel.math.Color.ofTransparent(0xc0a0f000.toInt()) + if (anyHovered) { + highlitSlots.add(hotbarSlot) + highlitSlots.add(inventorySlot) + } + fun color(highlit: Boolean) = + if (highlit) + me.shedaniel.math.Color.ofOpaque(0x00FF00) + else + me.shedaniel.math.Color.ofTransparent(0xc0a0f000.toInt()) if (TConfig.slotRenderLines == SlotRenderLinesMode.EVERYTHING || anyHovered) event.context.drawLine( invX + sx, invY + sy, hotX + sx, hotY + sy, - color + color(anyHovered) ) event.context.drawBorder(hotbarSlot.x + sx, hotbarSlot.y + sy, - 16, 16, color.color) + 16, 16, color(hotbarSlot in highlitSlots).color) event.context.drawBorder(inventorySlot.x + sx, inventorySlot.y + sy, - 16, 16, color.color) + 16, 16, color(inventorySlot in highlitSlots).color) } } @@ -339,11 +411,9 @@ object SlotLocking : FirmamentFeature { fun toggleSlotLock(slot: Slot) { val lockedSlots = lockedSlots ?: return - val boundSlots = DConfig.data?.boundSlots ?: mutableMapOf() + val boundSlots = DConfig.data?.boundSlots ?: BoundSlots() if (slot.inventory is PlayerInventory) { - if (boundSlots.entries.removeIf { - it.value == slot.index || it.key == slot.index - }) { + if (boundSlots.removeAllInvolving(slot.index)) { // intentionally do nothing } else if (slot.index in lockedSlots) { lockedSlots.remove(slot.index) @@ -378,7 +448,7 @@ object SlotLocking : FirmamentFeature { val isUUIDLocked = (it.slot.stack?.skyblockUUID) in (lockedUUIDs ?: setOf()) if (isSlotLocked || isUUIDLocked) { it.context.drawGuiTexture( - GuiRenderLayers.GUI_TEXTURED_NO_DEPTH, + RenderLayer::getGuiTexturedOverlay, when { isSlotLocked -> (Identifier.of("firmament:slot_locked")) diff --git a/src/main/kotlin/features/inventory/TimerInLore.kt b/src/main/kotlin/features/inventory/TimerInLore.kt index f1b77c6..309ea61 100644 --- a/src/main/kotlin/features/inventory/TimerInLore.kt +++ b/src/main/kotlin/features/inventory/TimerInLore.kt @@ -80,7 +80,8 @@ object TimerInLore { COMMUNITYPROJECTS("Contribute again", "Come back at"), CHOCOLATEFACTORY("Next Charge", "Available at"), STONKSAUCTION("Auction ends in", "Ends at"), - LIZSTONKREDEMPTION("Resets in:", "Resets at"); + LIZSTONKREDEMPTION("Resets in:", "Resets at"), + EVENTENDING("Event ends in:", "Ends at"); } val regex = diff --git a/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt b/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt index ee3ae8b..c4ea519 100644 --- a/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt +++ b/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt @@ -6,6 +6,7 @@ import io.github.notenoughupdates.moulconfig.xml.Bind import me.shedaniel.math.Point import me.shedaniel.math.Rectangle import org.lwjgl.glfw.GLFW +import net.minecraft.client.MinecraftClient import net.minecraft.client.gui.DrawContext import net.minecraft.client.gui.widget.ButtonWidget import net.minecraft.client.util.InputUtil @@ -55,6 +56,11 @@ class InventoryButtonEditor( super.close() } + override fun resize(client: MinecraftClient, width: Int, height: Int) { + lastGuiRect.move(MC.window.scaledWidth / 2 - lastGuiRect.width / 2, MC.window.scaledHeight / 2 - lastGuiRect.height / 2) + super.resize(client, width, height) + } + override fun init() { super.init() addDrawableChild( @@ -114,6 +120,13 @@ class InventoryButtonEditor( return newButtons } + override fun renderBackground(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { + context.matrices.push() + context.matrices.translate(0F, 0F, -15F) + super.renderBackground(context, mouseX, mouseY, delta) + context.matrices.pop() + } + override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { super.render(context, mouseX, mouseY, delta) context.matrices.push() diff --git a/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt b/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt index d5b5417..361e8d0 100644 --- a/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt +++ b/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt @@ -5,16 +5,22 @@ package moe.nea.firmament.features.inventory.buttons import me.shedaniel.math.Rectangle import kotlinx.serialization.Serializable import kotlinx.serialization.serializer +import kotlin.time.Duration.Companion.seconds +import net.minecraft.client.MinecraftClient +import net.minecraft.text.Text import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.HandledScreenClickEvent import moe.nea.firmament.events.HandledScreenForegroundEvent import moe.nea.firmament.events.HandledScreenPushREIEvent import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.FirmHoverComponent import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.util.MC import moe.nea.firmament.util.ScreenUtil +import moe.nea.firmament.util.TimeMark import moe.nea.firmament.util.data.DataHolder import moe.nea.firmament.util.accessors.getRectangle +import moe.nea.firmament.util.gold object InventoryButtons : FirmamentFeature { override val identifier: String @@ -24,6 +30,7 @@ object InventoryButtons : FirmamentFeature { val _openEditor by button("open-editor") { openEditor() } + val hoverText by toggle("hover-text") { true } } object DConfig : DataHolder<Data>(serializer(), identifier, ::Data) @@ -60,16 +67,36 @@ object InventoryButtons : FirmamentFeature { } } + var lastHoveredComponent: InventoryButton? = null + var lastMouseMove = TimeMark.farPast() + @Subscribe fun onRenderForeground(it: HandledScreenForegroundEvent) { val bounds = it.screen.getRectangle() + + var hoveredComponent: InventoryButton? = null for (button in getValidButtons()) { val buttonBounds = button.getBounds(bounds) it.context.matrices.push() it.context.matrices.translate(buttonBounds.minX.toFloat(), buttonBounds.minY.toFloat(), 0F) button.render(it.context) it.context.matrices.pop() + + if (buttonBounds.contains(it.mouseX, it.mouseY) && TConfig.hoverText && hoveredComponent == null) { + hoveredComponent = button + if (lastMouseMove.passedTime() > 0.6.seconds && lastHoveredComponent === button) { + it.context.drawTooltip( + MC.font, + listOf(Text.literal(button.command).gold()), + buttonBounds.minX - 15, + buttonBounds.maxY + 20, + ) + } + } } + if (hoveredComponent !== lastHoveredComponent) + lastMouseMove = TimeMark.now() + lastHoveredComponent = hoveredComponent lastRectangle = bounds } @@ -78,9 +105,9 @@ object InventoryButtons : FirmamentFeature { ScreenUtil.setScreenLater( InventoryButtonEditor( lastRectangle ?: Rectangle( - MC.window.scaledWidth / 2 - 100, - MC.window.scaledHeight / 2 - 100, - 200, 200, + MC.window.scaledWidth / 2 - 88, + MC.window.scaledHeight / 2 - 83, + 176, 166, ) ) ) diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt index 8fad4df..d7346c2 100644 --- a/src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt @@ -32,8 +32,8 @@ sealed interface StorageBackingHandle { StorageBackingHandle, HasBackingScreen companion object { - private val enderChestName = "^Ender Chest \\(([1-9])/[1-9]\\)$".toRegex() - private val backPackName = "^.+Backpack \\(Slot #([0-9]+)\\)$".toRegex() + private val enderChestName = "^Ender Chest (?:✦ )?\\(([1-9])/[1-9]\\)$".toRegex() + private val backPackName = "^.+Backpack (?:✦ )?\\(Slot #([0-9]+)\\)$".toRegex() /** * Parse a screen into a [StorageBackingHandle]. If this returns null it means that the screen is not diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt index 2e807de..2101915 100644 --- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt @@ -33,6 +33,7 @@ object StorageOverlay : FirmamentFeature { val inverseScroll by toggle("inverse-scroll") { false } val padding by integer("padding", 1, 20) { 5 } val margin by integer("margin", 1, 60) { 20 } + val itemsBlockScrolling by toggle("block-item-scrolling") { true } } fun adjustScrollSpeed(amount: Double): Double { diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt index 6092e26..81f058e 100644 --- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt @@ -9,6 +9,7 @@ import net.minecraft.entity.player.PlayerInventory import net.minecraft.screen.slot.Slot import moe.nea.firmament.mixins.accessor.AccessorHandledScreen import moe.nea.firmament.util.customgui.CustomGui +import moe.nea.firmament.util.focusedItemStack class StorageOverlayCustom( val handler: StorageBackingHandle, @@ -113,6 +114,8 @@ class StorageOverlayCustom( horizontalAmount: Double, verticalAmount: Double ): Boolean { + if (screen.focusedItemStack != null && StorageOverlay.TConfig.itemsBlockScrolling) + return false return overview.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount) } } diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt index 633a8fe..22f4dab 100644 --- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt @@ -218,7 +218,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) { } fun drawPlayerInventory(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { - val items = MC.player?.inventory?.main ?: return + val items = MC.player?.inventory?.mainStacks ?: return items.withIndex().forEach { (index, item) -> val (x, y) = getPlayerInventorySlotPosition(index) context.drawItem(item, x, y, 0) @@ -357,6 +357,10 @@ class StorageOverlayScreen : Screen(Text.literal("")) { return super.keyReleased(keyCode, scanCode, modifiers) } + override fun shouldCloseOnEsc(): Boolean { + return this === MC.screen // Fixes this UI closing the handled screen on Escape press. + } + override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { if (typeMCComponentInPlace( controlComponent, diff --git a/src/main/kotlin/features/inventory/storageoverlay/VirtualInventory.kt b/src/main/kotlin/features/inventory/storageoverlay/VirtualInventory.kt index 3b86184..d99acd7 100644 --- a/src/main/kotlin/features/inventory/storageoverlay/VirtualInventory.kt +++ b/src/main/kotlin/features/inventory/storageoverlay/VirtualInventory.kt @@ -11,6 +11,7 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder +import kotlin.jvm.optionals.getOrNull import net.minecraft.item.ItemStack import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtIo @@ -42,15 +43,15 @@ data class VirtualInventory( override fun deserialize(decoder: Decoder): VirtualInventory { val s = decoder.decodeString() val n = NbtIo.readCompressed(ByteArrayInputStream(s.decodeBase64Bytes()), NbtSizeTracker.of(100_000_000)) - val items = n.getList(INVENTORY, NbtCompound.COMPOUND_TYPE.toInt()) + val items = n.getList(INVENTORY).getOrNull() val ops = getOps() - return VirtualInventory(items.map { + return VirtualInventory(items?.map { it as NbtCompound if (it.isEmpty) ItemStack.EMPTY else ErrorUtil.catch("Could not deserialize item") { ItemStack.CODEC.parse(ops, it).orThrow }.or { ItemStack.EMPTY } - }) + } ?: listOf()) } fun getOps() = TolerantRegistriesOps(NbtOps.INSTANCE, MC.currentOrDefaultRegistries) |