aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2025-11-28 00:51:21 +0100
committerLinnea Gräf <nea@nea.moe>2025-11-28 00:51:21 +0100
commiteeb65f4913f9e6807e32edf1c94434a04ce3f239 (patch)
tree361f158d8a6b8b505104347736834085f1f53e23 /src/main
parent3dc343a4dfd0b5c30543321b77227d6c4fe5697e (diff)
downloadFirmament-mc-1.21.10.tar.gz
Firmament-mc-1.21.10.tar.bz2
Firmament-mc-1.21.10.zip
feat: itemlist setting component? early implHEADmc-1.21.10
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java2
-rw-r--r--src/main/kotlin/events/HandledScreenClickEvent.kt11
-rw-r--r--src/main/kotlin/features/items/recipes/ItemList.kt188
-rw-r--r--src/main/kotlin/features/items/recipes/RecipeScreen.kt2
4 files changed, 194 insertions, 9 deletions
diff --git a/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java b/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java
index c7555fb..bbeaf48 100644
--- a/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java
+++ b/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java
@@ -53,7 +53,7 @@ public abstract class MixinHandledScreen<T extends AbstractContainerMenu> {
private void onMouseReleased(MouseButtonEvent click, CallbackInfoReturnable<Boolean> cir) {
var self = (AbstractContainerScreen<?>) (Object) this;
var clickEvent = new HandledScreenClickEvent(self, click.x(), click.y(), click.button());
- var keyEvent = new HandledScreenKeyReleasedEvent(self, GenericInputAction.mouse(click), InputModifiers.current());
+ var keyEvent = new HandledScreenKeyReleasedEvent(self, GenericInputAction.mouse(click), InputModifiers.of(click.modifiers()));
if (HandledScreenClickEvent.Companion.publish(clickEvent).getCancelled()
|| HandledScreenKeyReleasedEvent.Companion.publish(keyEvent).getCancelled()) {
cir.setReturnValue(true);
diff --git a/src/main/kotlin/events/HandledScreenClickEvent.kt b/src/main/kotlin/events/HandledScreenClickEvent.kt
index b937907..c9890af 100644
--- a/src/main/kotlin/events/HandledScreenClickEvent.kt
+++ b/src/main/kotlin/events/HandledScreenClickEvent.kt
@@ -1,10 +1,11 @@
-
-
package moe.nea.firmament.events
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
-data class HandledScreenClickEvent(val screen: AbstractContainerScreen<*>, val mouseX: Double, val mouseY: Double, val button: Int) :
- FirmamentEvent.Cancellable() {
- companion object : FirmamentEventBus<HandledScreenClickEvent>()
+data class HandledScreenClickEvent(
+ val screen: AbstractContainerScreen<*>,
+ val mouseX: Double, val mouseY: Double, val button: Int
+) :
+ FirmamentEvent.Cancellable() {
+ companion object : FirmamentEventBus<HandledScreenClickEvent>()
}
diff --git a/src/main/kotlin/features/items/recipes/ItemList.kt b/src/main/kotlin/features/items/recipes/ItemList.kt
index f8268f4..9517a0b 100644
--- a/src/main/kotlin/features/items/recipes/ItemList.kt
+++ b/src/main/kotlin/features/items/recipes/ItemList.kt
@@ -1,19 +1,31 @@
package moe.nea.firmament.features.items.recipes
+import io.github.notenoughupdates.moulconfig.observer.GetSetter
+import io.github.notenoughupdates.moulconfig.observer.Property
import java.util.Optional
+import me.shedaniel.math.Rectangle
+import net.minecraft.client.gui.GuiGraphics
+import net.minecraft.client.gui.components.Renderable
+import net.minecraft.client.gui.components.events.GuiEventListener
+import net.minecraft.client.gui.navigation.ScreenAxis
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.client.input.MouseButtonEvent
+import net.minecraft.client.input.MouseButtonInfo
+import net.minecraft.network.chat.Component
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.HandledScreenClickEvent
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.render.drawLine
import moe.nea.firmament.util.skyblockId
object ItemList {
@@ -78,6 +90,115 @@ object ItemList {
var lastRenderPositions: List<Pair<ScreenRectangle, SBItemStack>> = listOf()
var lastHoveredItemStack: Pair<ScreenRectangle, SBItemStack>? = null
+ abstract class ItemListElement(
+ ) : Renderable, GuiEventListener {
+ abstract val rectangle: Rectangle
+ override fun setFocused(focused: Boolean) {
+ }
+
+ override fun isFocused(): Boolean {
+ return false
+ }
+
+ override fun isMouseOver(mouseX: Double, mouseY: Double): Boolean {
+ return rectangle.contains(mouseX, mouseY)
+ }
+ }
+
+ interface HasLabel {
+ fun component(): Component
+ }
+
+
+ class PopupSettingsElement<T : HasLabel>(
+ x: Int,
+ y: Int,
+ width: Int,
+ val selected: GetSetter<T>,
+ val options: List<T>,
+ ) : ItemListElement() {
+ override val rectangle: Rectangle = Rectangle(x, y, width, 4 + (MC.font.lineHeight + 2) * options.size)
+ fun bb(i: Int) =
+ Rectangle(
+ rectangle.minX, rectangle.minY + (2 + MC.font.lineHeight) * i + 2,
+ rectangle.width, MC.font.lineHeight
+ )
+
+ override fun render(
+ guiGraphics: GuiGraphics,
+ mouseX: Int,
+ mouseY: Int,
+ partialTick: Float
+ ) {
+ guiGraphics.fill(rectangle.minX, rectangle.minY, rectangle.maxX, rectangle.maxY, 0xFF000000.toInt())
+ guiGraphics.submitOutline(rectangle.x, rectangle.y, rectangle.width, rectangle.height, -1)
+ val sel = selected.get()
+ for ((index, element) in options.withIndex()) {
+ val b = bb(index)
+ val tw = MC.font.width(element.component())
+ guiGraphics.drawString(
+ MC.font, element.component(), b.centerX - tw / 2,
+ b.y + 1,
+ if (element == sel) 0xFFA0B000.toInt() else -1
+ )
+ if (b.contains(mouseX, mouseY))
+ guiGraphics.hLine(b.centerX - tw / 2, b.centerX + tw / 2 - 1, b.maxY + 1, -1)
+ }
+ }
+
+ override fun mouseClicked(event: MouseButtonEvent, isDoubleClick: Boolean): Boolean {
+ popupElement = null
+ for ((index, element) in options.withIndex()) {
+ val b = bb(index)
+ if (b.contains(event.x, event.y)) {
+ selected.set(element)
+ break
+ }
+ }
+ return true
+ }
+ }
+
+ class SettingElement<T : HasLabel>(
+ x: Int,
+ y: Int,
+ val selected: GetSetter<T>,
+ val options: List<T>
+ ) : ItemListElement() {
+ val height = MC.font.lineHeight + 4
+ val width = options.maxOf { MC.font.width(it.component()) } + 4
+ override val rectangle: Rectangle = Rectangle(x, y, width, height)
+
+ override fun render(
+ guiGraphics: GuiGraphics,
+ mouseX: Int,
+ mouseY: Int,
+ partialTick: Float
+ ) {
+ guiGraphics.drawCenteredString(MC.font, selected.get().component(), rectangle.centerX, rectangle.y + 2, -1)
+ if (isMouseOver(mouseX.toDouble(), mouseY.toDouble())) {
+ guiGraphics.hLine(rectangle.minX, rectangle.maxX - 1, rectangle.maxY - 2, -1)
+ }
+ }
+
+ override fun mouseClicked(
+ event: MouseButtonEvent,
+ isDoubleClick: Boolean
+ ): Boolean {
+ popupElement = PopupSettingsElement(
+ rectangle.x,
+ rectangle.y - options.size * (MC.font.lineHeight + 2) - 2,
+ width,
+ selected,
+ options
+ )
+ return true
+ }
+ }
+
+ var popupElement: ItemListElement? = null
+
+
fun findStackUnder(mouseX: Int, mouseY: Int): Pair<ScreenRectangle, SBItemStack>? {
val lhis = lastHoveredItemStack
if (lhis != null && lhis.first.containsPoint(mouseX, mouseY))
@@ -86,6 +207,33 @@ object ItemList {
}
@Subscribe
+ fun onClick(event: HandledScreenClickEvent) {
+ val pe = popupElement
+ val me = MouseButtonEvent(
+ event.mouseX, event.mouseY,
+ MouseButtonInfo(event.button, 0) // TODO: missing modifiers
+ )
+ if (pe != null) {
+ event.cancel()
+ if (!pe.isMouseOver(event.mouseX, event.mouseY)) {
+ popupElement = null
+ return
+ }
+ pe.mouseClicked(
+ me,
+ false
+ )
+ return
+ }
+ listElements.forEach {
+ if (it.isMouseOver(event.mouseX, event.mouseY))
+ it.mouseClicked(me, false)
+ }
+ }
+
+ var listElements = listOf<ItemListElement>()
+
+ @Subscribe
fun onRender(event: HandledScreenForegroundEvent) {
lastHoveredItemStack = null
lastRenderPositions = listOf()
@@ -94,16 +242,18 @@ object ItemList {
val screenWidth = event.screen.width
val rightThird = ScreenRectangle(
screenWidth - screenWidth / 3, 0,
- screenWidth / 3, event.screen.height
+ screenWidth / 3, event.screen.height - MC.font.lineHeight - 4
)
val coords = coordinates(rightThird, exclusions)
lastRenderPositions = coords.zip(potentiallyVisible.asSequence()).toList()
+ val isPopupHovered = popupElement?.isMouseOver(event.mouseX.toDouble(),event.mouseY.toDouble())
+ ?: false
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)) {
+ if (!isPopupHovered && pos.containsPoint(event.mouseX, event.mouseY)) {
lastHoveredItemStack = pos to stack
event.context.setTooltipForNextFrame(
MC.font,
@@ -116,5 +266,39 @@ object ItemList {
)
}
}
+ event.context.fill(
+ rightThird.left(),
+ rightThird.bottom(),
+ rightThird.right(),
+ event.screen.height,
+ 0xFF000000.toInt()
+ )
+ val le = mutableListOf<ItemListElement>()
+ le.add(
+ SettingElement(
+ 0,
+ rightThird.bottom(),
+ sortOrder,
+ SortOrder.entries
+ )
+ )
+ val bottomWidth = le.sumOf { it.rectangle.width + 2 } - 2
+ var startX = rightThird.getCenterInAxis(ScreenAxis.HORIZONTAL) - bottomWidth / 2
+ le.forEach {
+ it.rectangle.translate(startX, 0)
+ startX += it.rectangle.width + 2
+ }
+ le.forEach { it.render(event.context, event.mouseX, event.mouseY, event.delta) }
+ listElements = le
+ popupElement?.render(event.context, event.mouseX, event.mouseY, event.delta)
+ }
+
+ enum class SortOrder(val component: Component) : HasLabel {
+ NAME(Component.literal("Name")),
+ RARITY(Component.literal("Rarity"));
+
+ override fun component(): Component = component
}
+
+ val sortOrder = Property.of(SortOrder.NAME)
}
diff --git a/src/main/kotlin/features/items/recipes/RecipeScreen.kt b/src/main/kotlin/features/items/recipes/RecipeScreen.kt
index d365c0e..9a746f3 100644
--- a/src/main/kotlin/features/items/recipes/RecipeScreen.kt
+++ b/src/main/kotlin/features/items/recipes/RecipeScreen.kt
@@ -35,7 +35,7 @@ class RecipeScreen(
var scrollPortWidth: Int = 0
var heightEstimate: Int = 0
val gutter = 10
- override fun init() {// TODO: wrap all of this in a scroll layout
+ override fun init() {
super.init()
scrollViewport = minOf(height - 20, 250)
scrollPortWidth = 0