aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features/inventory
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/features/inventory')
-rw-r--r--src/main/kotlin/features/inventory/CraftingOverlay.kt2
-rw-r--r--src/main/kotlin/features/inventory/ItemHotkeys.kt5
-rw-r--r--src/main/kotlin/features/inventory/PetFeatures.kt57
-rw-r--r--src/main/kotlin/features/inventory/PriceData.kt147
-rw-r--r--src/main/kotlin/features/inventory/REIDependencyWarner.kt1
-rw-r--r--src/main/kotlin/features/inventory/TimerInLore.kt32
-rw-r--r--src/main/kotlin/features/inventory/WardrobeKeybinds.kt56
-rw-r--r--src/main/kotlin/features/inventory/buttons/InventoryButton.kt129
-rw-r--r--src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt115
-rw-r--r--src/main/kotlin/features/inventory/buttons/InventoryButtons.kt54
-rw-r--r--src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt4
-rw-r--r--src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt5
-rw-r--r--src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt3
-rw-r--r--src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt206
14 files changed, 591 insertions, 225 deletions
diff --git a/src/main/kotlin/features/inventory/CraftingOverlay.kt b/src/main/kotlin/features/inventory/CraftingOverlay.kt
index d2c79fd..f823086 100644
--- a/src/main/kotlin/features/inventory/CraftingOverlay.kt
+++ b/src/main/kotlin/features/inventory/CraftingOverlay.kt
@@ -8,6 +8,7 @@ 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.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.skyblockId
@@ -45,6 +46,7 @@ object CraftingOverlay : FirmamentFeature {
override val identifier: String
get() = "crafting-overlay"
+ @OptIn(ExpensiveItemCacheApi::class)
@Subscribe
fun onSlotRender(event: SlotRenderEvents.After) {
val slot = event.slot
diff --git a/src/main/kotlin/features/inventory/ItemHotkeys.kt b/src/main/kotlin/features/inventory/ItemHotkeys.kt
index 4aa8202..e826b31 100644
--- a/src/main/kotlin/features/inventory/ItemHotkeys.kt
+++ b/src/main/kotlin/features/inventory/ItemHotkeys.kt
@@ -3,12 +3,14 @@ package moe.nea.firmament.features.inventory
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
import moe.nea.firmament.gui.config.ManagedConfig
+import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.HypixelStaticData
import moe.nea.firmament.repo.ItemCache
import moe.nea.firmament.repo.ItemCache.asItemStack
import moe.nea.firmament.repo.ItemCache.isBroken
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.asBazaarStock
import moe.nea.firmament.util.focusedItemStack
import moe.nea.firmament.util.skyBlockId
import moe.nea.firmament.util.skyblock.SBItemUtil.getSearchName
@@ -18,6 +20,7 @@ object ItemHotkeys {
val openGlobalTradeInterface by keyBindingWithDefaultUnbound("global-trade-interface")
}
+ @OptIn(ExpensiveItemCacheApi::class)
@Subscribe
fun onHandledInventoryPress(event: HandledScreenKeyPressedEvent) {
if (!event.matches(TConfig.openGlobalTradeInterface)) {
@@ -26,7 +29,7 @@ object ItemHotkeys {
var item = event.screen.focusedItemStack ?: return
val skyblockId = item.skyBlockId ?: return
item = RepoManager.getNEUItem(skyblockId)?.asItemStack()?.takeIf { !it.isBroken } ?: item
- if (HypixelStaticData.hasBazaarStock(skyblockId)) {
+ if (HypixelStaticData.hasBazaarStock(skyblockId.asBazaarStock)) {
MC.sendCommand("bz ${item.getSearchName()}")
} else if (HypixelStaticData.hasAuctionHouseOffers(skyblockId)) {
MC.sendCommand("ahs ${item.getSearchName()}")
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..92bfc58 100644
--- a/src/main/kotlin/features/inventory/PriceData.kt
+++ b/src/main/kotlin/features/inventory/PriceData.kt
@@ -1,51 +1,120 @@
-
-
package moe.nea.firmament.features.inventory
+import org.lwjgl.glfw.GLFW
import net.minecraft.text.Text
+import net.minecraft.util.StringIdentifiable
import moe.nea.firmament.annotations.Subscribe
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.asBazaarStock
+import moe.nea.firmament.util.bold
+import moe.nea.firmament.util.darkGrey
+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"
-
- object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
- val tooltipEnabled by toggle("enable-always") { true }
- val enableKeybinding by keyBindingWithDefaultUnbound("enable-keybind")
- }
-
- override val config get() = TConfig
-
- @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))
- )
- }
- }
+ 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")
+ val stackSizeKey by keyBinding("stack-size-keybind") { GLFW.GLFW_KEY_LEFT_SHIFT }
+ val avgLowestBin by choice(
+ "avg-lowest-bin-days",
+ ) {
+ AvgLowestBin.THREEDAYAVGLOWESTBIN
+ }
+ }
+
+ enum class AvgLowestBin : StringIdentifiable {
+ OFF,
+ ONEDAYAVGLOWESTBIN,
+ THREEDAYAVGLOWESTBIN,
+ SEVENDAYAVGLOWESTBIN;
+
+ override fun asString(): String {
+ return name
+ }
+ }
+
+ 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) return
+ if (TConfig.enableKeybinding.isBound && !TConfig.enableKeybinding.isPressed()) return
+ val sbId = it.stack.skyBlockId
+ val stackSize = it.stack.count
+ val isShowingStack = TConfig.stackSizeKey.isPressed()
+ val multiplier = if (isShowingStack) stackSize else 1
+ val multiplierText =
+ if (isShowingStack)
+ tr("firmament.tooltip.multiply", "Showing prices for x${stackSize}").darkGrey()
+ else
+ tr(
+ "firmament.tooltip.multiply.hint",
+ "[${TConfig.stackSizeKey.format()}] to show x${stackSize}"
+ ).darkGrey()
+ val bazaarData = HypixelStaticData.bazaarData[sbId?.asBazaarStock]
+ val lowestBin = HypixelStaticData.lowestBin[sbId]
+ val avgBinValue: Double? = when (TConfig.avgLowestBin) {
+ AvgLowestBin.ONEDAYAVGLOWESTBIN -> HypixelStaticData.avg1dlowestBin[sbId]
+ AvgLowestBin.THREEDAYAVGLOWESTBIN -> HypixelStaticData.avg3dlowestBin[sbId]
+ AvgLowestBin.SEVENDAYAVGLOWESTBIN -> HypixelStaticData.avg7dlowestBin[sbId]
+ AvgLowestBin.OFF -> null
+ }
+ if (bazaarData != null) {
+ it.lines.add(Text.literal(""))
+ it.lines.add(multiplierText)
+ it.lines.add(
+ formatPrice(
+ tr("firmament.tooltip.bazaar.sell-order", "Bazaar Sell Order"),
+ bazaarData.quickStatus.sellPrice * multiplier
+ )
+ )
+ it.lines.add(
+ formatPrice(
+ tr("firmament.tooltip.bazaar.buy-order", "Bazaar Buy Order"),
+ bazaarData.quickStatus.buyPrice * multiplier
+ )
+ )
+ } else if (lowestBin != null) {
+ it.lines.add(Text.literal(""))
+ it.lines.add(multiplierText)
+ it.lines.add(
+ formatPrice(
+ tr("firmament.tooltip.ah.lowestbin", "Lowest BIN"),
+ lowestBin * multiplier
+ )
+ )
+ if (avgBinValue != null) {
+ it.lines.add(
+ formatPrice(
+ tr("firmament.tooltip.ah.avg-lowestbin", "AVG Lowest BIN"),
+ avgBinValue * multiplier
+ )
+ )
+ }
+ }
+ }
}
diff --git a/src/main/kotlin/features/inventory/REIDependencyWarner.kt b/src/main/kotlin/features/inventory/REIDependencyWarner.kt
index 7d88dd1..476759a 100644
--- a/src/main/kotlin/features/inventory/REIDependencyWarner.kt
+++ b/src/main/kotlin/features/inventory/REIDependencyWarner.kt
@@ -52,6 +52,7 @@ object REIDependencyWarner {
@Subscribe
fun checkREIDependency(event: SkyblockServerUpdateEvent) {
if (!SBData.isOnSkyblock) return
+ if (!RepoManager.Config.warnForMissingItemListMod) return
if (hasREI) return
if (sentWarning) return
sentWarning = true
diff --git a/src/main/kotlin/features/inventory/TimerInLore.kt b/src/main/kotlin/features/inventory/TimerInLore.kt
index 309ea61..cc1df9a 100644
--- a/src/main/kotlin/features/inventory/TimerInLore.kt
+++ b/src/main/kotlin/features/inventory/TimerInLore.kt
@@ -16,12 +16,14 @@ import moe.nea.firmament.util.SBData
import moe.nea.firmament.util.aqua
import moe.nea.firmament.util.grey
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
+import moe.nea.firmament.util.timestamp
import moe.nea.firmament.util.tr
import moe.nea.firmament.util.unformattedString
object TimerInLore {
object TConfig : ManagedConfig("lore-timers", Category.INVENTORY) {
val showTimers by toggle("show") { true }
+ val showCreationTimestamp by toggle("show-creation") { true }
val timerFormat by choice("format") { TimerFormat.SOCIALIST }
}
@@ -81,6 +83,9 @@ object TimerInLore {
CHOCOLATEFACTORY("Next Charge", "Available at"),
STONKSAUCTION("Auction ends in", "Ends at"),
LIZSTONKREDEMPTION("Resets in:", "Resets at"),
+ TIMEREMAININGS("Time Remaining:", "Ends at"),
+ COOLDOWN("Cooldown:", "Come back at"),
+ ONCOOLDOWN("On cooldown:", "Available at"),
EVENTENDING("Event ends in:", "Ends at");
}
@@ -88,6 +93,14 @@ object TimerInLore {
"(?i)(?:(?<years>[0-9]+) ?(y|years?) )?(?:(?<days>[0-9]+) ?(d|days?))? ?(?:(?<hours>[0-9]+) ?(h|hours?))? ?(?:(?<minutes>[0-9]+) ?(m|minutes?))? ?(?:(?<seconds>[0-9]+) ?(s|seconds?))?\\b".toRegex()
@Subscribe
+ fun creationInLore(event: ItemTooltipEvent) {
+ if (!TConfig.showCreationTimestamp) return
+ val timestamp = event.stack.timestamp ?: return
+ val formattedTimestamp = TConfig.timerFormat.formatter.format(ZonedDateTime.ofInstant(timestamp, ZoneId.systemDefault()))
+ event.lines.add(tr("firmament.lore.creationtimestamp", "Created at: $formattedTimestamp").grey())
+ }
+
+ @Subscribe
fun modifyLore(event: ItemTooltipEvent) {
if (!TConfig.showTimers) return
var lastTimer: ZonedDateTime? = null
@@ -108,9 +121,13 @@ object TimerInLore {
var baseLine = ZonedDateTime.now(SBData.hypixelTimeZone)
if (countdownType.isRelative) {
if (lastTimer == null) {
- event.lines.add(i + 1,
- tr("firmament.loretimer.missingrelative",
- "Found a relative countdown with no baseline (Firmament)").grey())
+ event.lines.add(
+ i + 1,
+ tr(
+ "firmament.loretimer.missingrelative",
+ "Found a relative countdown with no baseline (Firmament)"
+ ).grey()
+ )
continue
}
baseLine = lastTimer
@@ -120,10 +137,11 @@ object TimerInLore {
lastTimer = timer
val localTimer = timer.withZoneSameInstant(ZoneId.systemDefault())
// TODO: install approximate time stabilization algorithm
- event.lines.add(i + 1,
- Text.literal("${countdownType.label}: ")
- .grey()
- .append(Text.literal(TConfig.timerFormat.formatter.format(localTimer)).aqua())
+ event.lines.add(
+ i + 1,
+ Text.literal("${countdownType.label}: ")
+ .grey()
+ .append(Text.literal(TConfig.timerFormat.formatter.format(localTimer)).aqua())
)
}
}
diff --git a/src/main/kotlin/features/inventory/WardrobeKeybinds.kt b/src/main/kotlin/features/inventory/WardrobeKeybinds.kt
new file mode 100644
index 0000000..d797600
--- /dev/null
+++ b/src/main/kotlin/features/inventory/WardrobeKeybinds.kt
@@ -0,0 +1,56 @@
+package moe.nea.firmament.features.inventory
+
+import org.lwjgl.glfw.GLFW
+import net.minecraft.item.Items
+import net.minecraft.screen.slot.SlotActionType
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.events.HandledScreenKeyPressedEvent
+import moe.nea.firmament.features.FirmamentFeature
+import moe.nea.firmament.gui.config.ManagedConfig
+import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.mc.SlotUtils.clickLeftMouseButton
+import moe.nea.firmament.util.mc.SlotUtils.clickMiddleMouseButton
+
+object WardrobeKeybinds : FirmamentFeature {
+ override val identifier: String
+ get() = "wardrobe-keybinds"
+
+ object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
+ val wardrobeKeybinds by toggle("wardrobe-keybinds") { false }
+ val slotKeybinds = (1..9).map {
+ keyBinding("slot-$it") { GLFW.GLFW_KEY_0 + it }
+ }
+ }
+
+ override val config: ManagedConfig?
+ get() = TConfig
+
+ val slotKeybindsWithSlot = TConfig.slotKeybinds.withIndex().map { (index, keybinding) ->
+ index + 36 to keybinding
+ }
+
+ @Subscribe
+ fun switchSlot(event: HandledScreenKeyPressedEvent) {
+ if (MC.player == null || MC.world == null || MC.interactionManager == null) return
+
+ val regex = Regex("Wardrobe \\([12]/2\\)")
+ if (!regex.matches(event.screen.title.string)) return
+ if (!TConfig.wardrobeKeybinds) return
+
+ val slot =
+ slotKeybindsWithSlot
+ .find { event.matches(it.second.get()) }
+ ?.first ?: return
+
+ event.cancel()
+
+ val handler = event.screen.screenHandler
+ val invSlot = handler.getSlot(slot)
+
+ val itemStack = invSlot.stack
+ if (itemStack.item != Items.PINK_DYE && itemStack.item != Items.LIME_DYE) return
+
+ invSlot.clickLeftMouseButton(handler)
+ }
+
+}
diff --git a/src/main/kotlin/features/inventory/buttons/InventoryButton.kt b/src/main/kotlin/features/inventory/buttons/InventoryButton.kt
index a46bd76..955ae88 100644
--- a/src/main/kotlin/features/inventory/buttons/InventoryButton.kt
+++ b/src/main/kotlin/features/inventory/buttons/InventoryButton.kt
@@ -1,5 +1,3 @@
-
-
package moe.nea.firmament.features.inventory.buttons
import com.mojang.brigadier.StringReader
@@ -13,74 +11,93 @@ import net.minecraft.command.argument.ItemStackArgumentType
import net.minecraft.item.ItemStack
import net.minecraft.resource.featuretoggle.FeatureFlags
import net.minecraft.util.Identifier
+import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.ItemCache.asItemStack
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.collections.memoize
+import moe.nea.firmament.util.mc.arbitraryUUID
+import moe.nea.firmament.util.mc.createSkullItem
import moe.nea.firmament.util.render.drawGuiTexture
@Serializable
data class InventoryButton(
- var x: Int,
- var y: Int,
- var anchorRight: Boolean,
- var anchorBottom: Boolean,
- var icon: String? = "",
- var command: String? = "",
+ var x: Int,
+ var y: Int,
+ var anchorRight: Boolean,
+ var anchorBottom: Boolean,
+ var icon: String? = "",
+ var command: String? = "",
) {
- companion object {
- val itemStackParser by lazy {
- ItemStackArgumentType.itemStack(CommandRegistryAccess.of(MC.defaultRegistries,
- FeatureFlags.VANILLA_FEATURES))
- }
- val dimensions = Dimension(18, 18)
- val getItemForName = ::getItemForName0.memoize(1024)
- fun getItemForName0(icon: String): ItemStack {
- val repoItem = RepoManager.getNEUItem(SkyblockId(icon))
- var itemStack = repoItem.asItemStack(idHint = SkyblockId(icon))
- if (repoItem == null) {
- val giveSyntaxItem = if (icon.startsWith("/give") || icon.startsWith("give"))
- icon.split(" ", limit = 3).getOrNull(2) ?: icon
- else icon
- val componentItem =
- runCatching {
- itemStackParser.parse(StringReader(giveSyntaxItem)).createStack(1, false)
- }.getOrNull()
- if (componentItem != null)
- itemStack = componentItem
- }
- return itemStack
- }
- }
+ companion object {
+ val itemStackParser by lazy {
+ ItemStackArgumentType.itemStack(
+ CommandRegistryAccess.of(
+ MC.defaultRegistries,
+ FeatureFlags.VANILLA_FEATURES
+ )
+ )
+ }
+ val dimensions = Dimension(18, 18)
+ val getItemForName = ::getItemForName0.memoize(1024)
+ @OptIn(ExpensiveItemCacheApi::class)
+ fun getItemForName0(icon: String): ItemStack {
+ val repoItem = RepoManager.getNEUItem(SkyblockId(icon))
+ var itemStack = repoItem.asItemStack(idHint = SkyblockId(icon))
+ if (repoItem == null) {
+ when {
+ icon.startsWith("skull:") -> {
+ itemStack = createSkullItem(
+ arbitraryUUID,
+ "https://textures.minecraft.net/texture/${icon.substring("skull:".length)}"
+ )
+ }
+
+ else -> {
+ val giveSyntaxItem = if (icon.startsWith("/give") || icon.startsWith("give"))
+ icon.split(" ", limit = 3).getOrNull(2) ?: icon
+ else icon
+ val componentItem =
+ runCatching {
+ itemStackParser.parse(StringReader(giveSyntaxItem)).createStack(1, false)
+ }.getOrNull()
+ if (componentItem != null)
+ itemStack = componentItem
+ }
+ }
+ }
+ return itemStack
+ }
+ }
- fun render(context: DrawContext) {
- context.drawGuiTexture(
- 0,
- 0,
- 0,
- dimensions.width,
- dimensions.height,
- Identifier.of("firmament:inventory_button_background")
- )
- context.drawItem(getItem(), 1, 1)
- }
+ fun render(context: DrawContext) {
+ context.drawGuiTexture(
+ 0,
+ 0,
+ 0,
+ dimensions.width,
+ dimensions.height,
+ Identifier.of("firmament:inventory_button_background")
+ )
+ context.drawItem(getItem(), 1, 1)
+ }
- fun isValid() = !icon.isNullOrBlank() && !command.isNullOrBlank()
+ fun isValid() = !icon.isNullOrBlank() && !command.isNullOrBlank()
- fun getPosition(guiRect: Rectangle): Point {
- return Point(
- (if (anchorRight) guiRect.maxX else guiRect.minX) + x,
- (if (anchorBottom) guiRect.maxY else guiRect.minY) + y,
- )
- }
+ fun getPosition(guiRect: Rectangle): Point {
+ return Point(
+ (if (anchorRight) guiRect.maxX else guiRect.minX) + x,
+ (if (anchorBottom) guiRect.maxY else guiRect.minY) + y,
+ )
+ }
- fun getBounds(guiRect: Rectangle): Rectangle {
- return Rectangle(getPosition(guiRect), dimensions)
- }
+ fun getBounds(guiRect: Rectangle): Rectangle {
+ return Rectangle(getPosition(guiRect), dimensions)
+ }
- fun getItem(): ItemStack {
- return getItemForName(icon ?: "")
- }
+ fun getItem(): ItemStack {
+ return getItemForName(icon ?: "")
+ }
}
diff --git a/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt b/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt
index c4ea519..eecbd17 100644
--- a/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt
+++ b/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt
@@ -1,7 +1,9 @@
package moe.nea.firmament.features.inventory.buttons
import io.github.notenoughupdates.moulconfig.common.IItemStack
+import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent
import io.github.notenoughupdates.moulconfig.platform.ModernItemStack
+import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
import io.github.notenoughupdates.moulconfig.xml.Bind
import me.shedaniel.math.Point
import me.shedaniel.math.Rectangle
@@ -9,6 +11,7 @@ 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.gui.widget.TextWidget
import net.minecraft.client.util.InputUtil
import net.minecraft.text.Text
import net.minecraft.util.math.MathHelper
@@ -57,13 +60,46 @@ class InventoryButtonEditor(
}
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)
+ 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(
+ TextWidget(
+ lastGuiRect.minX,
+ 25,
+ lastGuiRect.width,
+ 9,
+ Text.translatable("firmament.inventory-buttons.delete"),
+ MC.font
+ ).alignCenter()
+ )
+ addDrawableChild(
+ TextWidget(
+ lastGuiRect.minX,
+ 40,
+ lastGuiRect.width,
+ 9,
+ Text.translatable("firmament.inventory-buttons.info"),
+ MC.font
+ ).alignCenter()
+ )
+ addDrawableChild(
+ ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.reset")) {
+ val newButtons = InventoryButtonTemplates.loadTemplate("TkVVQlVUVE9OUy9bXQ==")
+ if (newButtons != null)
+ buttons = moveButtons(newButtons.map { it.copy(command = it.command?.removePrefix("/")) })
+ }
+ .position(lastGuiRect.minX + 10, lastGuiRect.minY + 10)
+ .width(lastGuiRect.width - 20)
+ .build()
+ )
+ addDrawableChild(
ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.load-preset")) {
val t = ClipboardUtils.getTextContents()
val newButtons = InventoryButtonTemplates.loadTemplate(t)
@@ -82,6 +118,30 @@ class InventoryButtonEditor(
.width(lastGuiRect.width - 20)
.build()
)
+ addDrawableChild(
+ ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.simple-preset")) {
+ // Preset from NEU
+ // Credit: https://github.com/NotEnoughUpdates/NotEnoughUpdates/blob/9b1fcfebc646e9fb69f99006327faa3e734e5f51/src/main/resources/assets/notenoughupdates/invbuttons/presets.json#L900-L1348
+ val newButtons = InventoryButtonTemplates.loadTemplate("TkVVQlVUVE9OUy9bIntcblx0XCJ4XCI6IDE2MCxcblx0XCJ5XCI6IC0yMCxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcImJvbmVcIixcblx0XCJjb21tYW5kXCI6IFwicGV0c1wiXG59Iiwie1xuXHRcInhcIjogMTQwLFxuXHRcInlcIjogLTIwLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiBmYWxzZSxcblx0XCJpY29uXCI6IFwiYXJtb3Jfc3RhbmRcIixcblx0XCJjb21tYW5kXCI6IFwid2FyZHJvYmVcIlxufSIsIntcblx0XCJ4XCI6IDEyMCxcblx0XCJ5XCI6IC0yMCxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcImVuZGVyX2NoZXN0XCIsXG5cdFwiY29tbWFuZFwiOiBcInN0b3JhZ2VcIlxufSIsIntcblx0XCJ4XCI6IDEwMCxcblx0XCJ5XCI6IC0yMCxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcInNrdWxsOmQ3Y2M2Njg3NDIzZDA1NzBkNTU2YWM1M2UwNjc2Y2I1NjNiYmRkOTcxN2NkODI2OWJkZWJlZDZmNmQ0ZTdiZjhcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBpc2xhbmRcIlxufSIsIntcblx0XCJ4XCI6IDgwLFxuXHRcInlcIjogLTIwLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiBmYWxzZSxcblx0XCJpY29uXCI6IFwic2t1bGw6MzVmNGI0MGNlZjllMDE3Y2Q0MTEyZDI2YjYyNTU3ZjhjMWQ1YjE4OWRhMmU5OTUzNDIyMmJjOGNlYzdkOTE5NlwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGh1YlwiXG59Il0=")
+ if (newButtons != null)
+ buttons = moveButtons(newButtons.map { it.copy(command = it.command?.removePrefix("/")) })
+ }
+ .position(lastGuiRect.minX + 10, lastGuiRect.minY + 85)
+ .width(lastGuiRect.width - 20)
+ .build()
+ )
+ addDrawableChild(
+ ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.all-warps-preset")) {
+ // Preset from NEU
+ // Credit: https://github.com/NotEnoughUpdates/NotEnoughUpdates/blob/9b1fcfebc646e9fb69f99006327faa3e734e5f51/src/main/resources/assets/notenoughupdates/invbuttons/presets.json#L1817-L2276
+ val newButtons = InventoryButtonTemplates.loadTemplate("TkVVQlVUVE9OUy9bIntcblx0XCJ4XCI6IDIsXG5cdFwieVwiOiAtODQsXG5cdFwiYW5jaG9yUmlnaHRcIjogdHJ1ZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6YzljODg4MWU0MjkxNWE5ZDI5YmI2MWExNmZiMjZkMDU5OTEzMjA0ZDI2NWRmNWI0MzliM2Q3OTJhY2Q1NlwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGhvbWVcIlxufSIsIntcblx0XCJ4XCI6IDIsXG5cdFwieVwiOiAtNjQsXG5cdFwiYW5jaG9yUmlnaHRcIjogdHJ1ZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6ZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOFwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGh1YlwiXG59Iiwie1xuXHRcInhcIjogMixcblx0XCJ5XCI6IC00NCxcblx0XCJhbmNob3JSaWdodFwiOiB0cnVlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDo5YjU2ODk1Yjk2NTk4OTZhZDY0N2Y1ODU5OTIzOGFmNTMyZDQ2ZGI5YzFiMDM4OWI4YmJlYjcwOTk5ZGFiMzNkXCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgZHVuZ2Vvbl9odWJcIlxufSIsIntcblx0XCJ4XCI6IDIsXG5cdFwieVwiOiAtMjQsXG5cdFwiYW5jaG9yUmlnaHRcIjogdHJ1ZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6Nzg0MGI4N2Q1MjI3MWQyYTc1NWRlZGM4Mjg3N2UwZWQzZGY2N2RjYzQyZWE0NzllYzE0NjE3NmIwMjc3OWE1XCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgZW5kXCJcbn0iLCJ7XG5cdFwieFwiOiAxMDksXG5cdFwieVwiOiAtMTksXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IGZhbHNlLFxuXHRcImljb25cIjogXCJza3VsbDo4NmYwNmVhYTMwMDRhZWVkMDliM2Q1YjQ1ZDk3NmRlNTg0ZTY5MWMwZTljYWRlMTMzNjM1ZGU5M2QyM2I5ZWRiXCIsXG5cdFwiY29tbWFuZFwiOiBcImhvdG1cIlxufSIsIntcblx0XCJ4XCI6IDEzMCxcblx0XCJ5XCI6IC0xOSxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcIkVOREVSX0NIRVNUXCIsXG5cdFwiY29tbWFuZFwiOiBcInN0b3JhZ2VcIlxufSIsIntcblx0XCJ4XCI6IDE1MSxcblx0XCJ5XCI6IC0xOSxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcIkJPTkVcIixcblx0XCJjb21tYW5kXCI6IFwicGV0c1wiXG59Iiwie1xuXHRcInhcIjogLTE5LFxuXHRcInlcIjogMixcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcIkdPTERfQkxPQ0tcIixcblx0XCJjb21tYW5kXCI6IFwiYWhcIlxufSIsIntcblx0XCJ4XCI6IC0xOSxcblx0XCJ5XCI6IDIyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiBmYWxzZSxcblx0XCJpY29uXCI6IFwiR09MRF9CQVJESU5HXCIsXG5cdFwiY29tbWFuZFwiOiBcImJ6XCJcbn0iLCJ7XG5cdFwieFwiOiAtMTksXG5cdFwieVwiOiAtODQsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjQzOGNmM2Y4ZTU0YWZjM2IzZjkxZDIwYTQ5ZjMyNGRjYTE0ODYwMDdmZTU0NTM5OTA1NTUyNGMxNzk0MWY0ZGNcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBtdXNldW1cIlxufSIsIntcblx0XCJ4XCI6IC0xOSxcblx0XCJ5XCI6IC02NCxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6ZjQ4ODBkMmMxZTdiODZlODc1MjJlMjA4ODI2NTZmNDViYWZkNDJmOTQ5MzJiMmM1ZTBkNmVjYWE0OTBjYjRjXCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgZ2FyZGVuXCJcbn0iLCJ7XG5cdFwieFwiOiAtMTksXG5cdFwieVwiOiAtNDQsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjRkM2E2YmQ5OGFjMTgzM2M2NjRjNDkwOWZmOGQyZGM2MmNlODg3YmRjZjNjYzViMzg0ODY1MWFlNWFmNmJcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBiYXJuXCJcbn0iLCJ7XG5cdFwieFwiOiAtMTksXG5cdFwieVwiOiAtMjQsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjUxNTM5ZGRkZjllZDI1NWVjZTYzNDgxOTNjZDc1MDEyYzgyYzkzYWVjMzgxZjA1NTcyY2VjZjczNzk3MTFiM2JcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBkZXNlcnRcIlxufSIsIntcblx0XCJ4XCI6IDQsXG5cdFwieVwiOiAyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDo3M2JjOTY1ZDU3OWMzYzYwMzlmMGExN2ViN2MyZTZmYWY1MzhjN2E1ZGU4ZTYwZWM3YTcxOTM2MGQwYTg1N2E5XCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgZ29sZFwiXG59Iiwie1xuXHRcInhcIjogMjUsXG5cdFwieVwiOiAyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDo1NjlhMWYxMTQxNTFiNDUyMTM3M2YzNGJjMTRjMjk2M2E1MDExY2RjMjVhNjU1NGM0OGM3MDhjZDk2ZWJmY1wiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGRlZXBcIlxufSIsIntcblx0XCJ4XCI6IDQ2LFxuXHRcInlcIjogMixcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6MjFkYmUzMGIwMjdhY2JjZWI2MTI1NjNiZDg3N2NkN2ViYjcxOWVhNmVkMTM5OTAyN2RjZWU1OGJiOTA0OWQ0YVwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGNyeXN0YWxzXCJcbn0iLCJ7XG5cdFwieFwiOiA2Nyxcblx0XCJ5XCI6IDIsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjVjYmQ5ZjVlYzFlZDAwNzI1OTk5NjQ5MWU2OWZmNjQ5YTMxMDZjZjkyMDIyN2IxYmIzYTcxZWU3YTg5ODYzZlwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGZvcmdlXCJcbn0iLCJ7XG5cdFwieFwiOiA4OCxcblx0XCJ5XCI6IDIsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjZiMjBiMjNjMWFhMmJlMDI3MGYwMTZiNGM5MGQ2ZWU2YjgzMzBhMTdjZmVmODc4NjlkNmFkNjBiMmZmYmYzYjVcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBtaW5lc1wiXG59Iiwie1xuXHRcInhcIjogMTA5LFxuXHRcInlcIjogMixcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6YTIyMWY4MTNkYWNlZTBmZWY4YzU5Zjc2ODk0ZGJiMjY0MTU0NzhkOWRkZmM0NGMyZTcwOGE2ZDNiNzU0OWJcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBwYXJrXCJcbn0iLCJ7XG5cdFwieFwiOiAxMzAsXG5cdFwieVwiOiAyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDo5ZDdlM2IxOWFjNGYzZGVlOWM1Njc3YzEzNTMzM2I5ZDM1YTdmNTY4YjYzZDFlZjRhZGE0YjA2OGI1YTI1XCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgc3BpZGVyXCJcbn0iLCJ7XG5cdFwieFwiOiAxNTEsXG5cdFwieVwiOiAyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDpjMzY4N2UyNWM2MzJiY2U4YWE2MWUwZDY0YzI0ZTY5NGMzZWVhNjI5ZWE5NDRmNGNmMzBkY2ZiNGZiY2UwNzFcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBuZXRoZXJcIlxufSJd")
+ if (newButtons != null)
+ buttons = moveButtons(newButtons.map { it.copy(command = it.command?.removePrefix("/")) })
+ }
+ .position(lastGuiRect.minX + 10, lastGuiRect.minY + 110)
+ .width(lastGuiRect.width - 20)
+ .build()
+ )
}
private fun moveButtons(buttons: List<InventoryButton>): MutableList<InventoryButton> {
@@ -89,14 +149,20 @@ class InventoryButtonEditor(
val movedButtons = mutableListOf<InventoryButton>()
for (button in buttons) {
if ((!button.anchorBottom && !button.anchorRight && button.x > 0 && button.y > 0)) {
- MC.sendChat(tr("firmament.inventory-buttons.button-moved",
- "One of your imported buttons intersects with the inventory and has been moved to the top left."))
- movedButtons.add(button.copy(
- x = 0,
- y = -InventoryButton.dimensions.width,
- anchorRight = false,
- anchorBottom = false
- ))
+ MC.sendChat(
+ tr(
+ "firmament.inventory-buttons.button-moved",
+ "One of your imported buttons intersects with the inventory and has been moved to the top left."
+ )
+ )
+ movedButtons.add(
+ button.copy(
+ x = 0,
+ y = -InventoryButton.dimensions.width,
+ anchorRight = false,
+ anchorBottom = false
+ )
+ )
} else {
newButtons.add(button)
}
@@ -105,9 +171,11 @@ class InventoryButtonEditor(
val zeroRect = Rectangle(0, 0, 1, 1)
for (movedButton in movedButtons) {
fun getPosition(button: InventoryButton, index: Int) =
- button.copy(x = (index % 10) * InventoryButton.dimensions.width,
- y = (index / 10) * -InventoryButton.dimensions.height,
- anchorRight = false, anchorBottom = false)
+ button.copy(
+ x = (index % 10) * InventoryButton.dimensions.width,
+ y = (index / 10) * -InventoryButton.dimensions.height,
+ anchorRight = false, anchorBottom = false
+ )
while (true) {
val newPos = getPosition(movedButton, i++)
val newBounds = newPos.getBounds(zeroRect)
@@ -131,7 +199,12 @@ class InventoryButtonEditor(
super.render(context, mouseX, mouseY, delta)
context.matrices.push()
context.matrices.translate(0f, 0f, -10f)
- context.fill(lastGuiRect.minX, lastGuiRect.minY, lastGuiRect.maxX, lastGuiRect.maxY, -1)
+ PanelComponent.DefaultBackgroundRenderer.VANILLA
+ .render(
+ ModernRenderContext(context),
+ lastGuiRect.minX, lastGuiRect.minY,
+ lastGuiRect.width, lastGuiRect.height,
+ )
context.matrices.pop()
for (button in buttons) {
val buttonPosition = button.getBounds(lastGuiRect)
@@ -155,7 +228,8 @@ class InventoryButtonEditor(
if (super.mouseReleased(mouseX, mouseY, button)) return true
val clickedButton = buttons.firstOrNull { it.getBounds(lastGuiRect).contains(Point(mouseX, mouseY)) }
if (clickedButton != null && !justPerformedAClickAction) {
- createPopup(MoulConfigUtils.loadGui("button_editor_fragment", Editor(clickedButton)), Point(mouseX, mouseY))
+ if (InputUtil.isKeyPressed(MC.window.handle, InputUtil.GLFW_KEY_LEFT_CONTROL)) Editor(clickedButton).delete()
+ else createPopup(MoulConfigUtils.loadGui("button_editor_fragment", Editor(clickedButton)), Point(mouseX, mouseY))
return true
}
justPerformedAClickAction = false
@@ -193,14 +267,6 @@ class InventoryButtonEditor(
)
fun getCoordsForMouse(mx: Int, my: Int): AnchoredCoords? {
- if (lastGuiRect.contains(mx, my) || lastGuiRect.contains(
- Point(
- mx + InventoryButton.dimensions.width,
- my + InventoryButton.dimensions.height,
- )
- )
- ) return null
-
val anchorRight = mx > lastGuiRect.maxX
val anchorBottom = my > lastGuiRect.maxY
var offsetX = mx - if (anchorRight) lastGuiRect.maxX else lastGuiRect.minX
@@ -209,7 +275,10 @@ class InventoryButtonEditor(
offsetX = MathHelper.floor(offsetX / 20F) * 20
offsetY = MathHelper.floor(offsetY / 20F) * 20
}
- return AnchoredCoords(anchorRight, anchorBottom, offsetX, offsetY)
+ val rect = InventoryButton(offsetX, offsetY, anchorRight, anchorBottom).getBounds(lastGuiRect)
+ if (rect.intersects(lastGuiRect)) return null
+ val anchoredCoords = AnchoredCoords(anchorRight, anchorBottom, offsetX, offsetY)
+ return anchoredCoords
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
diff --git a/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt b/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt
index 92640c8..ab80d97 100644
--- a/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt
+++ b/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt
@@ -5,44 +5,50 @@ 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.gui.screen.ingame.HandledScreen
+import net.minecraft.client.gui.screen.ingame.InventoryScreen
+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.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
- get() = "inventory-buttons"
+object InventoryButtons {
- object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
+ object TConfig : ManagedConfig("inventory-buttons-config", Category.INVENTORY) {
val _openEditor by button("open-editor") {
openEditor()
}
+ val hoverText by toggle("hover-text") { true }
+ val onlyInv by toggle("only-inv") { false }
}
- object DConfig : DataHolder<Data>(serializer(), identifier, ::Data)
+ object DConfig : DataHolder<Data>(serializer(), "inventory-buttons", ::Data)
@Serializable
data class Data(
var buttons: MutableList<InventoryButton> = mutableListOf()
)
+ fun getValidButtons(screen: HandledScreen<*>): Sequence<InventoryButton> {
+ return DConfig.data.buttons.asSequence().filter { button ->
+ button.isValid() && (!TConfig.onlyInv || screen is InventoryScreen)
+ }
+ }
- override val config: ManagedConfig
- get() = TConfig
-
- fun getValidButtons() = DConfig.data.buttons.asSequence().filter { it.isValid() }
@Subscribe
fun onRectangles(it: HandledScreenPushREIEvent) {
val bounds = it.screen.getRectangle()
- for (button in getValidButtons()) {
+ for (button in getValidButtons(it.screen)) {
val buttonBounds = button.getBounds(bounds)
it.block(buttonBounds)
}
@@ -51,7 +57,7 @@ object InventoryButtons : FirmamentFeature {
@Subscribe
fun onClickScreen(it: HandledScreenClickEvent) {
val bounds = it.screen.getRectangle()
- for (button in getValidButtons()) {
+ for (button in getValidButtons(it.screen)) {
val buttonBounds = button.getBounds(bounds)
if (buttonBounds.contains(it.mouseX, it.mouseY)) {
MC.sendCommand(button.command!! /* non null invariant covered by getValidButtons */)
@@ -60,16 +66,36 @@ object InventoryButtons : FirmamentFeature {
}
}
+ var lastHoveredComponent: InventoryButton? = null
+ var lastMouseMove = TimeMark.farPast()
+
@Subscribe
fun onRenderForeground(it: HandledScreenForegroundEvent) {
- val bounds = it.screen.getRectangle()
- for (button in getValidButtons()) {
+ val bounds = it.screen.getRectangle()
+
+ var hoveredComponent: InventoryButton? = null
+ for (button in getValidButtons(it.screen)) {
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
}
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..ec62aa6 100644
--- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt
+++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt
@@ -27,12 +27,14 @@ object StorageOverlay : FirmamentFeature {
object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
val alwaysReplace by toggle("always-replace") { true }
+ val outlineActiveStoragePage by toggle("outline-active-page") { false }
val columns by integer("rows", 1, 10) { 3 }
val height by integer("height", 80, 3000) { 3 * 18 * 6 }
val scrollSpeed by integer("scroll-speed", 1, 50) { 10 }
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 {
@@ -100,7 +102,8 @@ object StorageOverlay : FirmamentFeature {
screen.customGui = StorageOverlayCustom(
currentHandler ?: return,
screen,
- storageOverlayScreen ?: (if (TConfig.alwaysReplace) StorageOverlayScreen() else return))
+ storageOverlayScreen ?: (if (TConfig.alwaysReplace) StorageOverlayScreen() else return)
+ )
}
fun rememberContent(handler: StorageBackingHandle?) {
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 22f4dab..84d0f2b 100644
--- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt
+++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt
@@ -47,15 +47,18 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
val PLAYER_Y_INSET = 3
val SLOT_SIZE = 18
val PADDING = 10
- val PAGE_WIDTH = SLOT_SIZE * 9
+ val PAGE_SLOTS_WIDTH = SLOT_SIZE * 9
+ val PAGE_WIDTH = PAGE_SLOTS_WIDTH + 4
val HOTBAR_X = 12
val HOTBAR_Y = 67
val MAIN_INVENTORY_Y = 9
val SCROLL_BAR_WIDTH = 8
val SCROLL_BAR_HEIGHT = 16
+ val CONTROL_X_INSET = 3
+ val CONTROL_Y_INSET = 5
val CONTROL_WIDTH = 70
- val CONTROL_BACKGROUND_WIDTH = CONTROL_WIDTH + PLAYER_Y_INSET
- val CONTROL_HEIGHT = 100
+ val CONTROL_BACKGROUND_WIDTH = CONTROL_WIDTH + CONTROL_X_INSET + 1
+ val CONTROL_HEIGHT = 50
}
var isExiting: Boolean = false
@@ -68,13 +71,14 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
val x = width / 2 - overviewWidth / 2
val overviewHeight = minOf(
height - PLAYER_HEIGHT - minOf(80, height / 10),
- StorageOverlay.TConfig.height)
+ StorageOverlay.TConfig.height
+ )
val innerScrollPanelHeight = overviewHeight - PADDING * 2
val y = height / 2 - (overviewHeight + PLAYER_HEIGHT) / 2
val playerX = width / 2 - PLAYER_WIDTH / 2
val playerY = y + overviewHeight - PLAYER_Y_INSET
- val controlX = x - CONTROL_WIDTH
- val controlY = y + overviewHeight / 2 - CONTROL_HEIGHT / 2
+ val controlX = playerX - CONTROL_WIDTH + CONTROL_X_INSET
+ val controlY = playerY - CONTROL_Y_INSET
val totalWidth = overviewWidth
val totalHeight = overviewHeight - PLAYER_Y_INSET + PLAYER_HEIGHT
}
@@ -100,6 +104,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
coerceScroll(StorageOverlay.adjustScrollSpeed(verticalAmount).toFloat())
return true
}
+
fun coerceScroll(offset: Float) {
scroll = (scroll + offset)
.coerceAtMost(getMaxScroll())
@@ -149,21 +154,29 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
fun editPages() {
isExiting = true
- val hs = MC.screen as? HandledScreen<*>
- if (StorageBackingHandle.fromScreen(hs) is StorageBackingHandle.Overview) {
- hs.customGui = null
- } else {
- MC.sendCommand("storage")
+ MC.instance.send {
+ val hs = MC.screen as? HandledScreen<*>
+ if (StorageBackingHandle.fromScreen(hs) is StorageBackingHandle.Overview) {
+ hs.customGui = null
+ hs.init(MC.instance, width, height)
+ } else {
+ MC.sendCommand("storage")
+ }
}
}
val guiContext = GuiContext(EmptyComponent())
private val knobStub = EmptyComponent()
- val editButton = FirmButtonComponent(TextComponent(tr("firmament.storage-overlay.edit-pages", "Edit Pages").string), action = ::editPages)
+ val editButton = FirmButtonComponent(
+ TextComponent(tr("firmament.storage-overlay.edit-pages", "Edit Pages").string),
+ action = ::editPages
+ )
val searchText = Property.of("") // TODO: sync with REI
- val searchField = TextFieldComponent(searchText, 100, GetSetter.constant(true),
- tr("firmament.storage-overlay.search.suggestion", "Search...").string,
- IMinecraft.instance.defaultFontRenderer)
+ val searchField = TextFieldComponent(
+ searchText, 100, GetSetter.constant(true),
+ tr("firmament.storage-overlay.search.suggestion", "Search...").string,
+ IMinecraft.instance.defaultFontRenderer
+ )
val controlComponent = PanelComponent(
ColumnComponent(
searchField,
@@ -186,25 +199,31 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
controllerBackground,
measurements.controlX,
measurements.controlY,
- CONTROL_BACKGROUND_WIDTH, CONTROL_HEIGHT)
+ CONTROL_BACKGROUND_WIDTH, CONTROL_HEIGHT
+ )
context.drawMCComponentInPlace(
controlComponent,
measurements.controlX, measurements.controlY,
CONTROL_WIDTH, CONTROL_HEIGHT,
- mouseX, mouseY)
+ mouseX, mouseY
+ )
}
fun drawBackgrounds(context: DrawContext) {
- context.drawGuiTexture(upperBackgroundSprite,
- measurements.x,
- measurements.y,
- measurements.overviewWidth,
- measurements.overviewHeight)
- context.drawGuiTexture(playerInventorySprite,
- measurements.playerX,
- measurements.playerY,
- PLAYER_WIDTH,
- PLAYER_HEIGHT)
+ context.drawGuiTexture(
+ upperBackgroundSprite,
+ measurements.x,
+ measurements.y,
+ measurements.overviewWidth,
+ measurements.overviewHeight
+ )
+ context.drawGuiTexture(
+ playerInventorySprite,
+ measurements.playerX,
+ measurements.playerY,
+ PLAYER_WIDTH,
+ PLAYER_HEIGHT
+ )
}
fun getPlayerInventorySlotPosition(int: Int): Pair<Int, Int> {
@@ -227,17 +246,21 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
}
fun getScrollBarRect(): Rectangle {
- return Rectangle(measurements.x + PADDING + measurements.innerScrollPanelWidth + PADDING,
- measurements.y + PADDING,
- SCROLL_BAR_WIDTH,
- measurements.innerScrollPanelHeight)
+ return Rectangle(
+ measurements.x + PADDING + measurements.innerScrollPanelWidth + PADDING,
+ measurements.y + PADDING,
+ SCROLL_BAR_WIDTH,
+ measurements.innerScrollPanelHeight
+ )
}
fun getScrollPanelInner(): Rectangle {
- return Rectangle(measurements.x + PADDING,
- measurements.y + PADDING,
- measurements.innerScrollPanelWidth,
- measurements.innerScrollPanelHeight)
+ return Rectangle(
+ measurements.x + PADDING,
+ measurements.y + PADDING,
+ measurements.innerScrollPanelWidth,
+ measurements.innerScrollPanelHeight
+ )
}
fun createScissors(context: DrawContext) {
@@ -257,12 +280,13 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
createScissors(context)
val data = StorageOverlay.Data.data ?: StorageData()
layoutedForEach(data) { rect, page, inventory ->
- drawPage(context,
- rect.x,
- rect.y,
- page, inventory,
- if (excluding == page) slots else null,
- slotOffset
+ drawPage(
+ context,
+ rect.x,
+ rect.y,
+ page, inventory,
+ if (excluding == page) slots else null,
+ slotOffset
)
}
context.disableScissor()
@@ -282,11 +306,13 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
knobGrabbed = false
return true
}
- if (clickMCComponentInPlace(controlComponent,
- measurements.controlX, measurements.controlY,
- CONTROL_WIDTH, CONTROL_HEIGHT,
- mouseX.toInt(), mouseY.toInt(),
- MouseEvent.Click(button, false))
+ if (clickMCComponentInPlace(
+ controlComponent,
+ measurements.controlX, measurements.controlY,
+ CONTROL_WIDTH, CONTROL_HEIGHT,
+ mouseX.toInt(), mouseY.toInt(),
+ MouseEvent.Click(button, false)
+ )
) return true
return super.mouseReleased(mouseX, mouseY, button)
}
@@ -322,11 +348,13 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
knobGrabbed = true
return true
}
- if (clickMCComponentInPlace(controlComponent,
- measurements.controlX, measurements.controlY,
- CONTROL_WIDTH, CONTROL_HEIGHT,
- mouseX.toInt(), mouseY.toInt(),
- MouseEvent.Click(button, true))
+ if (clickMCComponentInPlace(
+ controlComponent,
+ measurements.controlX, measurements.controlY,
+ CONTROL_WIDTH, CONTROL_HEIGHT,
+ mouseX.toInt(), mouseY.toInt(),
+ MouseEvent.Click(button, true)
+ )
) return true
return false
}
@@ -420,7 +448,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
val filter = getFilteredPages()
for ((page, inventory) in data.storageInventories.entries) {
if (page !in filter) continue
- val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 4 + textRenderer.fontHeight }
+ val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 6 + textRenderer.fontHeight }
?: 18
maxHeight = maxOf(maxHeight, currentHeight)
val rect = Rectangle(
@@ -452,22 +480,41 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
val inv = inventory.inventory
if (inv == null) {
context.drawGuiTexture(upperBackgroundSprite, x, y, PAGE_WIDTH, 18)
- context.drawText(textRenderer,
- Text.literal("TODO: open this page"),
- x + 4,
- y + 4,
- -1,
- true)
+ context.drawText(
+ textRenderer,
+ Text.literal("TODO: open this page"),
+ x + 4,
+ y + 4,
+ -1,
+ true
+ )
return 18
}
assertTrueOr(slots == null || slots.size == inv.stacks.size) { return 0 }
val name = page.defaultName()
- context.drawText(textRenderer, Text.literal(name), x + 4, y + 2,
- if (slots == null) 0xFFFFFFFF.toInt() else 0xFFFFFF00.toInt(), true)
- context.drawGuiTexture(slotRowSprite, x, y + 4 + textRenderer.fontHeight, PAGE_WIDTH, inv.rows * SLOT_SIZE)
+ val pageHeight = inv.rows * SLOT_SIZE + 8 + textRenderer.fontHeight
+ if (slots != null && StorageOverlay.TConfig.outlineActiveStoragePage)
+ context.drawBorder(
+ x,
+ y + 3 + textRenderer.fontHeight,
+ PAGE_WIDTH,
+ inv.rows * SLOT_SIZE + 4,
+ 0xFFFF00FF.toInt()
+ )
+ context.drawText(
+ textRenderer, Text.literal(name), x + 6, y + 3,
+ if (slots == null) 0xFFFFFFFF.toInt() else 0xFFFFFF00.toInt(), true
+ )
+ context.drawGuiTexture(
+ slotRowSprite,
+ x + 2,
+ y + 5 + textRenderer.fontHeight,
+ PAGE_SLOTS_WIDTH,
+ inv.rows * SLOT_SIZE
+ )
inv.stacks.forEachIndexed { index, stack ->
- val slotX = (index % 9) * SLOT_SIZE + x + 1
- val slotY = (index / 9) * SLOT_SIZE + y + 4 + textRenderer.fontHeight + 1
+ val slotX = (index % 9) * SLOT_SIZE + x + 3
+ val slotY = (index / 9) * SLOT_SIZE + y + 5 + textRenderer.fontHeight + 1
val fakeSlot = FakeSlot(stack, slotX, slotY)
if (slots == null) {
SlotRenderEvents.Before.publish(SlotRenderEvents.Before(context, fakeSlot))
@@ -480,22 +527,29 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
slot.y = slotY - slotOffset.y
}
}
- return inv.rows * SLOT_SIZE + 4 + textRenderer.fontHeight
+ return pageHeight + 6
}
fun getBounds(): List<Rectangle> {
return listOf(
- Rectangle(measurements.x,
- measurements.y,
- measurements.overviewWidth,
- measurements.overviewHeight),
- Rectangle(measurements.playerX,
- measurements.playerY,
- PLAYER_WIDTH,
- PLAYER_HEIGHT),
- Rectangle(measurements.controlX,
- measurements.controlY,
- CONTROL_WIDTH,
- CONTROL_HEIGHT))
+ Rectangle(
+ measurements.x,
+ measurements.y,
+ measurements.overviewWidth,
+ measurements.overviewHeight
+ ),
+ Rectangle(
+ measurements.playerX,
+ measurements.playerY,
+ PLAYER_WIDTH,
+ PLAYER_HEIGHT
+ ),
+ Rectangle(
+ measurements.controlX,
+ measurements.controlY,
+ CONTROL_WIDTH,
+ CONTROL_HEIGHT
+ )
+ )
}
}