diff options
| author | Linnea Gräf <nea@nea.moe> | 2025-11-25 00:23:57 +0100 |
|---|---|---|
| committer | Linnea Gräf <nea@nea.moe> | 2025-11-25 00:23:57 +0100 |
| commit | 707652b59e10371cf4826f9f65d653cac528c6bb (patch) | |
| tree | 65edeffdc0c14703771035222e18d7ff1cfd65b5 /src/main/kotlin/features | |
| parent | 6dd14e7225ff60361fe9f87020c424c0eb89a68b (diff) | |
| download | Firmament-707652b59e10371cf4826f9f65d653cac528c6bb.tar.gz Firmament-707652b59e10371cf4826f9f65d653cac528c6bb.tar.bz2 Firmament-707652b59e10371cf4826f9f65d653cac528c6bb.zip | |
feat: add item listHEADmc-1.21.10
Diffstat (limited to 'src/main/kotlin/features')
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 |
