aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2025-11-25 00:23:57 +0100
committerLinnea Gräf <nea@nea.moe>2025-11-25 00:23:57 +0100
commit707652b59e10371cf4826f9f65d653cac528c6bb (patch)
tree65edeffdc0c14703771035222e18d7ff1cfd65b5 /src/main/kotlin/features
parent6dd14e7225ff60361fe9f87020c424c0eb89a68b (diff)
downloadFirmament-707652b59e10371cf4826f9f65d653cac528c6bb.tar.gz
Firmament-707652b59e10371cf4826f9f65d653cac528c6bb.tar.bz2
Firmament-707652b59e10371cf4826f9f65d653cac528c6bb.zip
feat: add item listHEADmc-1.21.10
Diffstat (limited to 'src/main/kotlin/features')
-rw-r--r--src/main/kotlin/features/inventory/SlotLocking.kt19
-rw-r--r--src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt7
-rw-r--r--src/main/kotlin/features/items/recipes/ItemList.kt120
-rw-r--r--src/main/kotlin/features/items/recipes/ItemSlotWidget.kt49
-rw-r--r--src/main/kotlin/features/items/recipes/RecipeWidget.kt4
-rw-r--r--src/main/kotlin/features/mining/HotmPresets.kt7
6 files changed, 167 insertions, 39 deletions
diff --git a/src/main/kotlin/features/inventory/SlotLocking.kt b/src/main/kotlin/features/inventory/SlotLocking.kt
index 09afe80..fca40c8 100644
--- a/src/main/kotlin/features/inventory/SlotLocking.kt
+++ b/src/main/kotlin/features/inventory/SlotLocking.kt
@@ -42,6 +42,7 @@ import moe.nea.firmament.util.CommonSoundEffects
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SBData
import moe.nea.firmament.util.SkyBlockIsland
+import moe.nea.firmament.util.accessors.castAccessor
import moe.nea.firmament.util.data.Config
import moe.nea.firmament.util.data.ManagedConfig
import moe.nea.firmament.util.data.ProfileSpecificDataHolder
@@ -295,7 +296,7 @@ object SlotLocking {
fun onLockUUID(it: HandledScreenKeyPressedEvent) {
if (!it.matches(TConfig.lockUUID)) return
val inventory = MC.handledScreen ?: return
- inventory as AccessorHandledScreen
+ inventory.castAccessor()
val slot = inventory.focusedSlot_Firmament ?: return
val stack = slot.item ?: return
@@ -330,7 +331,7 @@ object SlotLocking {
@Subscribe
fun onLockSlotKeyRelease(it: HandledScreenKeyReleasedEvent) {
val inventory = MC.handledScreen ?: return
- inventory as AccessorHandledScreen
+ inventory.castAccessor()
val slot = inventory.focusedSlot_Firmament
val storedSlot = storedLockingSlot ?: return
@@ -364,7 +365,7 @@ object SlotLocking {
fun onRenderAllBoundSlots(event: HandledScreenForegroundEvent) {
val boundSlots = currentWorldData?.boundSlots ?: return
fun findByIndex(index: Int) = event.screen.getSlotByIndex(index, true)
- val accScreen = event.screen as AccessorHandledScreen
+ val accScreen = event.screen.castAccessor()
val sx = accScreen.x_Firmament
val sy = accScreen.y_Firmament
val highlitSlots = mutableSetOf<Slot>()
@@ -409,14 +410,20 @@ object SlotLocking {
@Subscribe
fun onRenderCurrentDraggingSlot(event: HandledScreenForegroundEvent) {
val draggingSlot = storedLockingSlot ?: return
- val accScreen = event.screen as AccessorHandledScreen
+ val accScreen = event.screen.castAccessor()
val hoveredSlot = accScreen.focusedSlot_Firmament
?.takeIf { it.container is Inventory }
?.takeIf { it == draggingSlot || it.isHotbar() != draggingSlot.isHotbar() }
val sx = accScreen.x_Firmament
val sy = accScreen.y_Firmament
val (borderX, borderY) = draggingSlot.lineCenter()
- event.context.submitOutline(draggingSlot.x + sx, draggingSlot.y + sy, 16, 16, 0xFF00FF00u.toInt()) // TODO: 1.21.10
+ event.context.submitOutline(
+ draggingSlot.x + sx,
+ draggingSlot.y + sy,
+ 16,
+ 16,
+ 0xFF00FF00u.toInt()
+ ) // TODO: 1.21.10
if (hoveredSlot == null) {
event.context.drawLine(
borderX + sx, borderY + sy,
@@ -477,7 +484,7 @@ object SlotLocking {
@Subscribe
fun onLockSlot(it: HandledScreenKeyPressedEvent) {
val inventory = MC.handledScreen ?: return
- inventory as AccessorHandledScreen
+ inventory.castAccessor()
val slot = inventory.focusedSlot_Firmament ?: return
if (slot.container !is Inventory) return
diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt
index f291dba..98e8085 100644
--- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt
+++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt
@@ -11,6 +11,7 @@ import net.minecraft.client.input.KeyEvent
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.inventory.Slot
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
+import moe.nea.firmament.util.accessors.castAccessor
import moe.nea.firmament.util.customgui.CustomGui
import moe.nea.firmament.util.focusedItemStack
@@ -42,7 +43,7 @@ class StorageOverlayCustom(
override fun onInit() {
overview.init(Minecraft.getInstance(), screen.width, screen.height)
overview.init()
- screen as AccessorHandledScreen
+ screen.castAccessor()
screen.x_Firmament = overview.measurements.x
screen.y_Firmament = overview.measurements.y
screen.backgroundWidth_Firmament = overview.measurements.totalWidth
@@ -96,7 +97,7 @@ class StorageOverlayCustom(
delta,
(handler as? StorageBackingHandle.Page)?.storagePageSlot,
screen.menu.slots.take(screen.menu.rowCount * 9).drop(9),
- Point((screen as AccessorHandledScreen).x_Firmament, screen.y_Firmament)
+ Point((screen.castAccessor()).x_Firmament, screen.y_Firmament)
)
overview.drawScrollBar(drawContext)
overview.drawControls(drawContext, mouseX, mouseY)
@@ -106,7 +107,7 @@ class StorageOverlayCustom(
val index = slot.containerSlot
if (index in 0..<36) {
val (x, y) = overview.getPlayerInventorySlotPosition(index)
- slot.x = x - (screen as AccessorHandledScreen).x_Firmament
+ slot.x = x - (screen.castAccessor()).x_Firmament
slot.y = y - screen.y_Firmament
} else {
slot.x = -100000
diff --git a/src/main/kotlin/features/items/recipes/ItemList.kt b/src/main/kotlin/features/items/recipes/ItemList.kt
new file mode 100644
index 0000000..f8268f4
--- /dev/null
+++ b/src/main/kotlin/features/items/recipes/ItemList.kt
@@ -0,0 +1,120 @@
+package moe.nea.firmament.features.items.recipes
+
+import java.util.Optional
+import net.minecraft.client.gui.navigation.ScreenRectangle
+import net.minecraft.client.gui.screens.Screen
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
+import net.minecraft.world.item.ItemStack
+import net.minecraft.world.item.Items
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.api.v1.FirmamentAPI
+import moe.nea.firmament.events.HandledScreenForegroundEvent
+import moe.nea.firmament.events.ReloadRegistrationEvent
+import moe.nea.firmament.repo.RepoManager
+import moe.nea.firmament.repo.SBItemStack
+import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.accessors.castAccessor
+import moe.nea.firmament.util.skyblockId
+
+object ItemList {
+ // TODO: add a global toggle for this and RecipeRegistry
+
+ fun collectExclusions(screen: Screen): Set<ScreenRectangle> {
+ val exclusions = mutableSetOf<ScreenRectangle>()
+ if (screen is AbstractContainerScreen<*>) {
+ val screenHandler = screen.castAccessor()
+ exclusions.add(
+ ScreenRectangle(
+ screenHandler.x_Firmament,
+ screenHandler.y_Firmament,
+ screenHandler.backgroundWidth_Firmament,
+ screenHandler.backgroundHeight_Firmament
+ )
+ )
+ }
+ FirmamentAPI.getInstance().extensions
+ .forEach { extension ->
+ for (rectangle in extension.getExclusionZones(screen)) {
+ if (exclusions.any { it.encompasses(rectangle) })
+ continue
+ exclusions.add(rectangle)
+ }
+ }
+
+ return exclusions
+ }
+
+ var reachableItems = listOf<SBItemStack>()
+ var pageOffset = 0
+ fun recalculateVisibleItems() {
+ reachableItems = RepoManager.neuRepo.items
+ .items.values.map { SBItemStack(it.skyblockId) }
+ }
+
+ @Subscribe
+ fun onReload(event: ReloadRegistrationEvent) {
+ event.repo.registerReloadListener { recalculateVisibleItems() }
+ }
+
+ fun coordinates(outer: ScreenRectangle, exclusions: Collection<ScreenRectangle>): Sequence<ScreenRectangle> {
+ val entryWidth = 18
+ val columns = outer.width / entryWidth
+ val rows = outer.height / entryWidth
+ val lowX = outer.right() - columns * entryWidth
+ val lowY = outer.top()
+ return generateSequence(0) { it + 1 }
+ .map {
+ val xIndex = it % columns
+ val yIndex = it / columns
+ ScreenRectangle(
+ lowX + xIndex * entryWidth, lowY + yIndex * entryWidth,
+ entryWidth, entryWidth
+ )
+ }
+ .take(rows * columns)
+ .filter { candidate -> exclusions.none { it.intersects(candidate) } }
+ }
+
+ var lastRenderPositions: List<Pair<ScreenRectangle, SBItemStack>> = listOf()
+ var lastHoveredItemStack: Pair<ScreenRectangle, SBItemStack>? = null
+
+ fun findStackUnder(mouseX: Int, mouseY: Int): Pair<ScreenRectangle, SBItemStack>? {
+ val lhis = lastHoveredItemStack
+ if (lhis != null && lhis.first.containsPoint(mouseX, mouseY))
+ return lhis
+ return lastRenderPositions.firstOrNull { it.first.containsPoint(mouseX, mouseY) }
+ }
+
+ @Subscribe
+ fun onRender(event: HandledScreenForegroundEvent) {
+ lastHoveredItemStack = null
+ lastRenderPositions = listOf()
+ val exclusions = collectExclusions(event.screen)
+ val potentiallyVisible = reachableItems.subList(pageOffset, reachableItems.size)
+ val screenWidth = event.screen.width
+ val rightThird = ScreenRectangle(
+ screenWidth - screenWidth / 3, 0,
+ screenWidth / 3, event.screen.height
+ )
+ val coords = coordinates(rightThird, exclusions)
+
+ lastRenderPositions = coords.zip(potentiallyVisible.asSequence()).toList()
+ lastRenderPositions.forEach { (pos, stack) ->
+ val realStack = stack.asLazyImmutableItemStack()
+ val toRender = realStack ?: ItemStack(Items.PAINTING)
+ event.context.renderItem(toRender, pos.left() + 1, pos.top() + 1)
+ if (pos.containsPoint(event.mouseX, event.mouseY)) {
+ lastHoveredItemStack = pos to stack
+ event.context.setTooltipForNextFrame(
+ MC.font,
+ if (realStack != null)
+ ItemSlotWidget.getTooltip(realStack)
+ else
+ stack.estimateLore(),
+ Optional.empty(),
+ event.mouseX, event.mouseY
+ )
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/features/items/recipes/ItemSlotWidget.kt b/src/main/kotlin/features/items/recipes/ItemSlotWidget.kt
index c47c8ca..b659643 100644
--- a/src/main/kotlin/features/items/recipes/ItemSlotWidget.kt
+++ b/src/main/kotlin/features/items/recipes/ItemSlotWidget.kt
@@ -71,36 +71,37 @@ class ItemSlotWidget(
companion object {
val SHORT_NUM_CUTOFF = 1000
var canUseTooltipEvent = true
- }
- fun getTooltip(itemStack: ItemStack): List<Component> {
- val lore = mutableListOf(itemStack.displayNameAccordingToNbt)
- lore.addAll(itemStack.loreAccordingToNbt)
- if (canUseTooltipEvent) {
- try {
- ItemTooltipCallback.EVENT.invoker().getTooltip(
- itemStack, Item.TooltipContext.EMPTY,
- TooltipFlag.NORMAL, lore
+ fun getTooltip(itemStack: ItemStack): List<Component> {
+ val lore = mutableListOf(itemStack.displayNameAccordingToNbt)
+ lore.addAll(itemStack.loreAccordingToNbt)
+ if (canUseTooltipEvent) {
+ try {
+ ItemTooltipCallback.EVENT.invoker().getTooltip(
+ itemStack, Item.TooltipContext.EMPTY,
+ TooltipFlag.NORMAL, lore
+ )
+ } catch (ex: Exception) {
+ canUseTooltipEvent = false
+ ErrorUtil.softError("Failed to use vanilla tooltips", ex)
+ }
+ } else {
+ ItemTooltipEvent.publish(
+ ItemTooltipEvent(
+ itemStack,
+ Item.TooltipContext.EMPTY,
+ TooltipFlag.NORMAL,
+ lore
+ )
)
- } catch (ex: Exception) {
- canUseTooltipEvent = false
- ErrorUtil.softError("Failed to use vanilla tooltips", ex)
}
- } else {
- ItemTooltipEvent.publish(
- ItemTooltipEvent(
- itemStack,
- Item.TooltipContext.EMPTY,
- TooltipFlag.NORMAL,
- lore
- )
- )
+ if (itemStack.count >= SHORT_NUM_CUTOFF && lore.isNotEmpty())
+ lore.add(1, Component.literal("${itemStack.count}x").darkGrey())
+ return lore
}
- if (itemStack.count >= SHORT_NUM_CUTOFF && lore.isNotEmpty())
- lore.add(1, Component.literal("${itemStack.count}x").darkGrey())
- return lore
}
+
override fun tick() {
if (SavedKeyBinding.isShiftDown()) return
if (content.size <= 1) return
diff --git a/src/main/kotlin/features/items/recipes/RecipeWidget.kt b/src/main/kotlin/features/items/recipes/RecipeWidget.kt
index b0591b2..f13707c 100644
--- a/src/main/kotlin/features/items/recipes/RecipeWidget.kt
+++ b/src/main/kotlin/features/items/recipes/RecipeWidget.kt
@@ -27,10 +27,6 @@ abstract class RecipeWidget : GuiEventListener, Renderable, NarratableEntry {
this._focused = focused
}
- override fun getRectangle(): ScreenRectangle {
- return rect.asScreenRectangle()
- }
-
override fun isFocused(): Boolean {
return this._focused
}
diff --git a/src/main/kotlin/features/mining/HotmPresets.kt b/src/main/kotlin/features/mining/HotmPresets.kt
index 5316211..4930f90 100644
--- a/src/main/kotlin/features/mining/HotmPresets.kt
+++ b/src/main/kotlin/features/mining/HotmPresets.kt
@@ -24,6 +24,7 @@ import moe.nea.firmament.util.ClipboardUtils
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.TemplateUtil
import moe.nea.firmament.util.TimeMark
+import moe.nea.firmament.util.accessors.castAccessor
import moe.nea.firmament.util.customgui.CustomGui
import moe.nea.firmament.util.customgui.customGui
import moe.nea.firmament.util.mc.CommonTextures
@@ -124,7 +125,7 @@ object HotmPresets {
screen.height / 2 - 100,
300, 200
)
- val screen = screen as AccessorHandledScreen
+ val screen = screen.castAccessor()
screen.x_Firmament = bounds.x
screen.y_Firmament = bounds.y
screen.backgroundWidth_Firmament = bounds.width
@@ -156,7 +157,9 @@ object HotmPresets {
}
}
if (allRows == coveredRows) {
- ClipboardUtils.setTextContent(TemplateUtil.encodeTemplate(SHARE_PREFIX, HotmPreset(
+ ClipboardUtils.setTextContent(
+ TemplateUtil.encodeTemplate(
+ SHARE_PREFIX, HotmPreset(
unlockedPerks.map { PerkPreset(it) }
)))
hasAll = true