From 42978b6d7c7a67396fdc5895fa5160830513256f Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Mon, 12 May 2025 20:02:18 +0300 Subject: [PATCH 01/14] Remove item pickup log functionality from the api --- ...=> BeaconBlockEntityRendererAccessor.java} | 2 +- .../me/nobaboy/nobaaddons/api/InventoryAPI.kt | 137 ++---------------- .../nobaboy/nobaaddons/api/skyblock/PetAPI.kt | 2 +- .../nobaaddons/api/skyblock/SkyBlockAPI.kt | 8 +- .../api/skyblock/events/hoppity/HoppityAPI.kt | 2 +- .../skyblock/events/mythological/DianaAPI.kt | 2 +- .../events/impl/client/InventoryEvents.kt | 4 +- .../events/mythological/AnnounceRareDrops.kt | 9 +- .../nobaaddons/utils/InventoryUtils.kt | 6 +- .../nobaaddons/utils/render/RenderUtils.kt | 4 +- 10 files changed, 35 insertions(+), 141 deletions(-) rename src/main/java/me/nobaboy/nobaaddons/mixins/accessors/{BeaconBlockEntityRendererInvoker.java => BeaconBlockEntityRendererAccessor.java} (92%) diff --git a/src/main/java/me/nobaboy/nobaaddons/mixins/accessors/BeaconBlockEntityRendererInvoker.java b/src/main/java/me/nobaboy/nobaaddons/mixins/accessors/BeaconBlockEntityRendererAccessor.java similarity index 92% rename from src/main/java/me/nobaboy/nobaaddons/mixins/accessors/BeaconBlockEntityRendererInvoker.java rename to src/main/java/me/nobaboy/nobaaddons/mixins/accessors/BeaconBlockEntityRendererAccessor.java index 2f2acf55..374d50f9 100644 --- a/src/main/java/me/nobaboy/nobaaddons/mixins/accessors/BeaconBlockEntityRendererInvoker.java +++ b/src/main/java/me/nobaboy/nobaaddons/mixins/accessors/BeaconBlockEntityRendererAccessor.java @@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(BeaconBlockEntityRenderer.class) -public interface BeaconBlockEntityRendererInvoker { +public interface BeaconBlockEntityRendererAccessor { @Invoker static void invokeRenderBeam( MatrixStack matrices, diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/api/InventoryAPI.kt b/src/main/kotlin/me/nobaboy/nobaaddons/api/InventoryAPI.kt index 3919b744..0f2ccffb 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/api/InventoryAPI.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/api/InventoryAPI.kt @@ -1,67 +1,23 @@ package me.nobaboy.nobaaddons.api -//? if >=1.21.5 { -/*import me.nobaboy.nobaaddons.mixins.accessors.PlayerInventoryAccessor -*///?} - -import me.nobaboy.nobaaddons.api.skyblock.SkyBlockAPI -import me.nobaboy.nobaaddons.config.NobaConfig import me.nobaboy.nobaaddons.data.InventoryData import me.nobaboy.nobaaddons.events.impl.client.InventoryEvents import me.nobaboy.nobaaddons.events.impl.client.PacketEvents -import me.nobaboy.nobaaddons.events.impl.client.TickEvents -import me.nobaboy.nobaaddons.events.impl.client.WorldEvents import me.nobaboy.nobaaddons.utils.MCUtils -import me.nobaboy.nobaaddons.utils.TextUtils.buildLiteral -import me.nobaboy.nobaaddons.utils.Timestamp import net.minecraft.client.gui.screen.ChatScreen -import net.minecraft.entity.player.PlayerInventory import net.minecraft.network.packet.c2s.play.CloseHandledScreenC2SPacket import net.minecraft.network.packet.s2c.play.CloseScreenS2CPacket import net.minecraft.network.packet.s2c.play.InventoryS2CPacket import net.minecraft.network.packet.s2c.play.OpenScreenS2CPacket import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket -import net.minecraft.text.Text -import net.minecraft.util.Formatting -import java.util.concurrent.ConcurrentHashMap object InventoryAPI { - private val MERCHANT_COUNT = Regex("x\\d+") - private const val SKYBLOCK_MENU_SLOT = 8 - + private var currentScreen: Screen? = null private var currentInventory: InventoryData? = null - private var currentWindow: Window? = null - - private var inventorySuppressTime = Timestamp.distantPast() - private var previousItemCounts: Map? = null - val itemLog = ConcurrentHashMap() - - private fun shouldSuppressItemLogUpdate(): Boolean = inventorySuppressTime.elapsedSeconds() < 2 fun init() { - TickEvents.every(5, this::onQuarterSecond) PacketEvents.SEND.register(this::onPacketSend) PacketEvents.POST_RECEIVE.register(this::onPacketReceive) - WorldEvents.LOAD.register { debounceItemLog() } - } - - private fun onQuarterSecond(event: TickEvents.Tick) { - val player = event.client.player - if(!SkyBlockAPI.inSkyBlock || player == null) { - previousItemCounts = null - itemLog.clear() - return - } - - if(event.client.currentScreen == null) { - val current = player.inventory.itemNamesToCount() - previousItemCounts?.takeIf { !shouldSuppressItemLogUpdate() }?.let { updateItemLog(it, current) } - previousItemCounts = current - } - - itemLog.entries.removeIf { (_, diff) -> - diff.timestamp.elapsedSeconds() > NobaConfig.inventory.itemPickupLog.timeoutSeconds - } } private fun onPacketSend(event: PacketEvents.Send) { @@ -80,11 +36,11 @@ object InventoryAPI { } private fun onScreenOpen(packet: OpenScreenS2CPacket) { - currentWindow = Window(packet.syncId, packet.name.string) + currentScreen = Screen(packet.syncId, packet.name.string) } private fun onInventory(packet: InventoryS2CPacket) { - if(packet.syncId != currentWindow?.id) return + if(packet.syncId != currentScreen?.id) return val slotCount = packet.contents.size - 36 val items = packet.contents @@ -94,22 +50,19 @@ object InventoryAPI { .associate { it.index to it.value } .toMutableMap() - currentInventory = InventoryData(currentWindow!!.id, currentWindow!!.title, slotCount, items).also(::ready) + currentInventory = InventoryData(currentScreen!!.id, currentScreen!!.title, slotCount, items).also(::ready) } private fun onSlotUpdate(packet: ScreenHandlerSlotUpdateS2CPacket) { - if(packet.syncId != currentWindow?.id) { - InventoryEvents.SLOT_UPDATE.dispatch(InventoryEvents.SlotUpdate(packet.stack, packet.slot)) - return - } + if(packet.syncId != currentScreen?.id) return - val inventory = currentInventory ?: return + val currentInventory = currentInventory ?: return val slot = packet.slot - if(slot >= inventory.slotCount) return - packet.stack?.let { inventory.items[slot] = it } + if(slot >= currentInventory.slotCount) return + currentInventory.items[slot] = packet.stack - InventoryEvents.UPDATE.dispatch(InventoryEvents.Update(inventory)) + InventoryEvents.UPDATE.dispatch(InventoryEvents.Update(currentInventory)) } private fun ready(inventory: InventoryData) { @@ -117,78 +70,10 @@ object InventoryAPI { InventoryEvents.UPDATE.dispatch(InventoryEvents.Update(inventory)) } - private fun debounceItemLog() { - previousItemCounts = null - inventorySuppressTime = Timestamp.now() - } - private fun close(sameName: Boolean = false) { if(MCUtils.client.currentScreen is ChatScreen) return InventoryEvents.CLOSE.dispatch(InventoryEvents.Close(sameName)) } - private fun updateItemLog(previous: Map, current: Map) { - // this MUST be annotated, as the kotlin compiler can't figure out the typing automatically from getOrPut, - // despite the fact that intellij doesn't throw any warnings. - val diffs = buildMap { - for(item in (previous.keys + current.keys)) { - val previousCount = previous[item] ?: 0 - val currentCount = current[item] ?: 0 - if(previousCount == currentCount) continue - getOrPut(item) { ItemDiff(item) }.change += currentCount - previousCount - } - } - - for((name, diff) in diffs) { - if(diff.change == 0) continue - val logDiff = itemLog.getOrPut(name) { ItemDiff(name) } - logDiff.change += diff.change - logDiff.timestamp = Timestamp.now() - } - } - - private fun Text.removeMerchantCount(): Text { - if(siblings.size <= 1) return this - val last = siblings.last() - // celeste — Today at 01:19 - // i have reworded this comment like 10 times now - // i cannot figure out a way to properly express how much i hate having to do this - if(last.string.matches(MERCHANT_COUNT) && last.style.color?.rgb == Formatting.DARK_GRAY.colorValue!!) { - val copy = copy() - copy.siblings.removeLast() - val name = copy.siblings.removeLast() - val content = name.string.removeSuffix(" ") - copy.append(buildLiteral(content) { style = name.style }) - return copy - } - return this - } - - private fun PlayerInventory.itemNamesToCount(): Map = buildMap { - //? if >=1.21.5 { - /*val main = (this@itemNamesToCount as PlayerInventoryAccessor).main - *///?} - - for(slot in 0 until main.size) { - if(slot == SKYBLOCK_MENU_SLOT) { - continue - } - - val item = main[slot] - if(item.isEmpty) continue - val name = item.name.removeMerchantCount() - - merge(name, item.count, Int::plus) - } - // TODO fix for 1.21.5 -// offHand.firstOrNull()?.let { merge(name, it.count, Int::plus) } - } - - data class Window(val id: Int, val title: String) - - data class ItemDiff( - val name: Text, - var change: Int = 0, - var timestamp: Timestamp = Timestamp.now(), - ) -} + data class Screen(val id: Int, val title: String) +} \ No newline at end of file diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/PetAPI.kt b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/PetAPI.kt index 0ab26704..596bba5c 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/PetAPI.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/PetAPI.kt @@ -65,7 +65,7 @@ object PetAPI { if(event.button != GLFW.GLFW_MOUSE_BUTTON_1) return if(event.actionType != SlotActionType.PICKUP) return - getPetData(event.itemStack)?.let { changePet(it) } + getPetData(event.stack)?.let { changePet(it) } } private fun onChatMessage(event: ChatMessageEvents.Chat) { diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/SkyBlockAPI.kt b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/SkyBlockAPI.kt index e5c39694..cd3a0ca6 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/SkyBlockAPI.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/SkyBlockAPI.kt @@ -99,9 +99,11 @@ object SkyBlockAPI { private fun onLocationPacket(packet: ClientboundLocationPacket) { currentServer = packet.serverType.getOrNull() - currentIsland = SkyBlockIsland.getByName(packet.mode.getOrNull() ?: return) - if(currentIsland != SkyBlockIsland.UNKNOWN) Scheduler.schedule(2) { - SkyBlockEvents.ISLAND_CHANGE.dispatch(SkyBlockEvents.IslandChange(currentIsland)) + val newIsland = packet.mode.map(SkyBlockIsland::getByName).orElse(SkyBlockIsland.UNKNOWN) + + if(newIsland != currentIsland) Scheduler.schedule(2) { + SkyBlockEvents.ISLAND_CHANGE.dispatch(SkyBlockEvents.IslandChange(newIsland)) + currentIsland = newIsland } } diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/events/hoppity/HoppityAPI.kt b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/events/hoppity/HoppityAPI.kt index e2895ba9..6a2df1b3 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/events/hoppity/HoppityAPI.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/events/hoppity/HoppityAPI.kt @@ -17,7 +17,7 @@ object HoppityAPI { val inRelevantIsland: Boolean get() = unsupportedIslands.none { it.inIsland() } val hasLocatorInHand: Boolean get() = MCUtils.player?.mainHandStack?.skyBlockId == LOCATOR - val hasLocatorInHotbar: Boolean get() = InventoryUtils.getItemsInHotbar().any { it.skyBlockId == LOCATOR } + val hasLocatorInHotbar: Boolean get() = InventoryUtils.getHotbarItems().any { it.skyBlockId == LOCATOR } private val unsupportedIslands = listOf( SkyBlockIsland.PRIVATE_ISLAND, diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/events/mythological/DianaAPI.kt b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/events/mythological/DianaAPI.kt index 6c704cb1..53963bf0 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/events/mythological/DianaAPI.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/events/mythological/DianaAPI.kt @@ -14,6 +14,6 @@ object DianaAPI { val isActive: Boolean get() = SkyBlockIsland.HUB.inIsland() && isRitualActive && hasSpadeInHotbar private val isRitualActive: Boolean get() = MayorPerk.MYTHOLOGICAL_RITUAL.isActive() - private val hasSpadeInHotbar: Boolean get() = InventoryUtils.getItemsInHotbar().any { it.skyBlockId == SPADE } + private val hasSpadeInHotbar: Boolean get() = InventoryUtils.getHotbarItems().any { it.skyBlockId == SPADE } fun hasSpadeInHand(player: PlayerEntity): Boolean = player.mainHandStack.skyBlockId == SPADE } \ No newline at end of file diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/events/impl/client/InventoryEvents.kt b/src/main/kotlin/me/nobaboy/nobaaddons/events/impl/client/InventoryEvents.kt index 57548f24..7a921851 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/events/impl/client/InventoryEvents.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/events/impl/client/InventoryEvents.kt @@ -37,6 +37,6 @@ object InventoryEvents { data class Open(val inventory: InventoryData) : Event data class Close(val sameName: Boolean) : Event data class Update(val inventory: InventoryData) : Event - data class SlotUpdate(val itemStack: ItemStack, val slot: Int) : Event - data class SlotClick(val itemStack: ItemStack, val button: Int, val slot: Int, val actionType: SlotActionType) : Event + data class SlotUpdate(val stack: ItemStack, val slot: Int) : Event + data class SlotClick(val stack: ItemStack, val button: Int, val slot: Int, val actionType: SlotActionType) : Event } diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/events/mythological/AnnounceRareDrops.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/events/mythological/AnnounceRareDrops.kt index bb59ba71..fa42ae3e 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/events/mythological/AnnounceRareDrops.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/events/mythological/AnnounceRareDrops.kt @@ -1,5 +1,7 @@ package me.nobaboy.nobaaddons.features.events.mythological +import me.nobaboy.nobaaddons.api.skyblock.events.mythological.DianaAPI +import me.nobaboy.nobaaddons.config.NobaConfig import me.nobaboy.nobaaddons.events.impl.client.InventoryEvents import me.nobaboy.nobaaddons.utils.TextUtils.buildText import me.nobaboy.nobaaddons.utils.TimedSet @@ -11,6 +13,9 @@ import net.minecraft.util.Formatting import kotlin.time.Duration.Companion.seconds object AnnounceRareDrops { + private val config get() = NobaConfig.events.mythological + private val enabled: Boolean get() = config.announceRareDrops && DianaAPI.isActive + private val uuidCache = TimedSet(10.seconds) private val rareDrops = listOf( @@ -25,7 +30,9 @@ object AnnounceRareDrops { } private fun onSlotUpdate(event: InventoryEvents.SlotUpdate) { - val itemStack = event.itemStack + if(!enabled) return + + val itemStack = event.stack val item = itemStack.asSkyBlockItem ?: return if(item.id !in rareDrops) return diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/utils/InventoryUtils.kt b/src/main/kotlin/me/nobaboy/nobaaddons/utils/InventoryUtils.kt index 0985b049..7549da70 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/utils/InventoryUtils.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/utils/InventoryUtils.kt @@ -10,6 +10,9 @@ import net.minecraft.item.ItemStack object InventoryUtils { fun openInventoryName(): String? = (MCUtils.client.currentScreen as? GenericContainerScreen)?.title?.string + fun getInventoryItems(): List = getInventoryItemsOrNull().orEmpty() + fun getHotbarItems(): List = getInventoryItemsOrNull()?.slice(0..8).orEmpty() + fun getInventoryItemsOrNull(): List? { //? if >=1.21.5 { /*return (MCUtils.player?.inventory as? PlayerInventoryAccessor)?.main @@ -17,7 +20,4 @@ object InventoryUtils { return MCUtils.player?.inventory?.main //?} } - fun getInventoryItems(): List = getInventoryItemsOrNull()?.filterNotNull().orEmpty() - - fun getItemsInHotbar(): List = getInventoryItemsOrNull()?.slice(0..8)?.filterNotNull().orEmpty() } \ No newline at end of file diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/utils/render/RenderUtils.kt b/src/main/kotlin/me/nobaboy/nobaaddons/utils/render/RenderUtils.kt index 8d6ed072..5fced00b 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/utils/render/RenderUtils.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/utils/render/RenderUtils.kt @@ -15,7 +15,7 @@ import com.mojang.blaze3d.systems.RenderSystem import org.lwjgl.opengl.GL11 //?} -import me.nobaboy.nobaaddons.mixins.accessors.BeaconBlockEntityRendererInvoker +import me.nobaboy.nobaaddons.mixins.accessors.BeaconBlockEntityRendererAccessor import me.nobaboy.nobaaddons.utils.MCUtils import me.nobaboy.nobaaddons.utils.NobaColor import me.nobaboy.nobaaddons.utils.NobaVec @@ -245,7 +245,7 @@ object RenderUtils { matrices.push() matrices.translate(x, y, z) - BeaconBlockEntityRendererInvoker.invokeRenderBeam( + BeaconBlockEntityRendererAccessor.invokeRenderBeam( matrices, context.consumers(), //? if >=1.21.5 { From d75966da4c778ce769e7693e5cfb8833cb34b756 Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Mon, 12 May 2025 20:18:43 +0300 Subject: [PATCH 02/14] Annnd it works again --- .../config/categories/InventoryCategory.kt | 5 + .../config/configs/InventoryConfig.kt | 1 + .../features/inventory/ItemPickupLog.kt | 169 ++++++++++++++++-- 3 files changed, 164 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/config/categories/InventoryCategory.kt b/src/main/kotlin/me/nobaboy/nobaaddons/config/categories/InventoryCategory.kt index e1c10a94..b59c42d6 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/config/categories/InventoryCategory.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/config/categories/InventoryCategory.kt @@ -204,6 +204,11 @@ object InventoryCategory { name = CommonText.Config.ENABLED booleanController() } + add({ inventory.itemPickupLog::compactLines }) { + name = tr("nobaaddons.config.inventory.itemPickupLog.compactLines", "Compact Lines") + require { option(enabled) } + booleanController() + } add({ inventory.itemPickupLog::timeoutSeconds }) { name = tr("nobaaddons.config.inventory.itemPickupLog.timeout", "Expire After") require { option(enabled) } diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/config/configs/InventoryConfig.kt b/src/main/kotlin/me/nobaboy/nobaaddons/config/configs/InventoryConfig.kt index fb2119f4..3f89ae5e 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/config/configs/InventoryConfig.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/config/configs/InventoryConfig.kt @@ -53,6 +53,7 @@ class InventoryConfig { class ItemPickupLog { var enabled = false + var compactLines = false var timeoutSeconds = 5 } } \ No newline at end of file diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index 50e0fe00..9cb3a243 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -1,26 +1,174 @@ package me.nobaboy.nobaaddons.features.inventory -import me.nobaboy.nobaaddons.api.InventoryAPI +import me.nobaboy.nobaaddons.api.skyblock.SkyBlockAPI import me.nobaboy.nobaaddons.config.NobaConfig import me.nobaboy.nobaaddons.config.UISettings +import me.nobaboy.nobaaddons.events.impl.client.TickEvents +import me.nobaboy.nobaaddons.events.impl.skyblock.SkyBlockEvents import me.nobaboy.nobaaddons.ui.TextHudElement import me.nobaboy.nobaaddons.ui.UIManager +import me.nobaboy.nobaaddons.utils.NumberUtils.addSeparators +import me.nobaboy.nobaaddons.utils.TextUtils.buildLiteral import me.nobaboy.nobaaddons.utils.TextUtils.buildText import me.nobaboy.nobaaddons.utils.TextUtils.green import me.nobaboy.nobaaddons.utils.TextUtils.literal import me.nobaboy.nobaaddons.utils.TextUtils.red +import me.nobaboy.nobaaddons.utils.Timestamp import me.nobaboy.nobaaddons.utils.tr import net.minecraft.client.gui.DrawContext +import net.minecraft.entity.player.PlayerInventory import net.minecraft.text.Text +import net.minecraft.util.Formatting import kotlin.math.abs +import kotlin.time.Duration.Companion.seconds object ItemPickupLog { + private val MERCHANT_COUNT = Regex("x\\d+") + private const val SKYBLOCK_MENU_SLOT = 8 + private val config get() = NobaConfig.inventory.itemPickupLog + private val enabled: Boolean get() = config.enabled && SkyBlockAPI.inSkyBlock + + private val items = mutableMapOf() + private var suppressTime = Timestamp.distantPast() + + private val addedItems = mutableMapOf() + private val removedItems = mutableMapOf() fun init() { + SkyBlockEvents.ISLAND_CHANGE.register { reset() } + TickEvents.TICK.register(this::onTick) UIManager.add(PickupLogHudElement) } + private fun onTick(event: TickEvents.Tick) { + if(!enabled) return + if(event.client.currentScreen != null) return + + val player = event.client.player ?: return + + val newItems = player.inventory.nameToCount() + val oldItems = mutableMapOf().apply { putAll(items) } + items.clear() + + newItems.forEach { (name, count) -> + items[name] = items.getOrDefault(name, 0) + count + } + + // this check is here solely to update items because it's empty to start with + if(suppressTime.elapsedSince() < 2.seconds) return + detectItemChanges(items, oldItems) + } + + // TODO either remove current and just use items straight out or suppress this + private fun detectItemChanges(current: Map, previous: Map) { + val names = current.keys + previous.keys + + for(name in names) { + val delta = (current[name] ?: 0) - (previous[name] ?: 0) + if(delta == 0) continue + + val map = if (delta > 0) addedItems else removedItems + val previousChange = map[name]?.change ?: 0 + map[name] = ItemEntry(previousChange + abs(delta)) + } + } + + private fun PlayerInventory.nameToCount(): Map = buildMap { + //? if >=1.21.5 { + /*val main = (this@itemNamesToCount as PlayerInventoryAccessor).main + *///?} + + main.forEachIndexed { slot, stack -> + if(slot == SKYBLOCK_MENU_SLOT || stack.isEmpty) return@forEachIndexed + + val name = stack.name.removeMerchantCount() + merge(name, stack.count, Int::plus) + } + + // TODO fix for 1.21.5 and remove merchant count from name just in case +// offHand.firstOrNull()?.let { merge(name, it.count, Int::plus) } + } + + // TODO maybe clean this up, can't get rid of it cuz we need to remove the count either way + private fun Text.removeMerchantCount(): Text { + if(siblings.size <= 1) return this + val last = siblings.last() + + // celeste — Today at 01:19 + // i have reworded this comment like 10 times now + // i cannot figure out a way to properly express how much i hate having to do this + if(last.string.matches(MERCHANT_COUNT) && last.style.color?.rgb == Formatting.DARK_GRAY.colorValue!!) { + val copy = copy() + copy.siblings.removeLast() + val name = copy.siblings.removeLast() + val content = name.string.removeSuffix(" ") + copy.append(buildLiteral(content) { style = name.style }) + return copy + } + + return this + } + + // TODO wtf is this, split into 2 functions and call whichever based on config.compactLines + private fun buildDisplayLines(): List { + addedItems.values.removeIf { it.expired } + removedItems.values.removeIf { it.expired } + + return buildList { + if(config.compactLines) { + val allNames = (addedItems.keys + removedItems.keys).toSet() + + for (name in allNames) { + val added = addedItems[name]?.change ?: 0 + val removed = removedItems[name]?.change ?: 0 + + val delta = added - removed + if(delta == 0) continue + + add(buildText { + literal(if(delta > 0) "+${delta.addSeparators()}x " else "-${(-delta).addSeparators()}x ") { + if(delta > 0) green() else red() + } + append(name) + }) + } + } else { + for((name, addEntry) in addedItems) { + add(buildText { + literal("+${addEntry.change.addSeparators()}x ") { green() } + append(name) + }) + + removedItems[name]?.let { removeEntry -> + add(buildText { + literal("-${removeEntry.change.addSeparators()}x ") { red() } + append(name) + }) + } + } + + // Add only removed items that weren't also added + for((name, removeEntry) in removedItems) { + if(name !in addedItems) { + add(buildText { + literal("-${removeEntry.change.addSeparators()}x ") { red() } + append(name) + }) + } + } + } + } + } + + + private fun reset() { + items.clear() + addedItems.clear() + removedItems.clear() + suppressTime = Timestamp.now() + } + private object PickupLogHudElement : TextHudElement(UISettings.itemPickupLog) { override val name: Text = tr("nobaaddons.ui.itemPickupLog", "Item Pickup Log") override val size: Pair = 125 to 175 @@ -29,16 +177,15 @@ object ItemPickupLog { override val maxScale: Float = 1f override fun renderText(context: DrawContext) { - renderLines(context, InventoryAPI.itemLog.filter { (_, diff) -> diff.change != 0 }.map { (name, diff) -> - buildText { - if(diff.change < 0) { - literal("- ${abs(diff.change)}x ") { red() } - } else { - literal("+ ${diff.change}x ") { green() } - } - append(name) - } - }) + renderLines(context, buildDisplayLines()) } } + + private data class ItemEntry( + var change: Int = 0, + var timestamp: Timestamp = Timestamp.now(), + ) { + val expired: Boolean + get() = timestamp.elapsedSince() > config.timeoutSeconds.seconds + } } \ No newline at end of file From e9f7944dbca1005ef316e6be197af492d69998f5 Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Mon, 12 May 2025 20:24:09 +0300 Subject: [PATCH 03/14] Questionable but idc --- .../kotlin/me/nobaboy/nobaaddons/api/skyblock/PetAPI.kt | 4 +--- .../features/events/mythological/AnnounceRareDrops.kt | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/PetAPI.kt b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/PetAPI.kt index 596bba5c..302f0204 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/PetAPI.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/api/skyblock/PetAPI.kt @@ -54,9 +54,7 @@ object PetAPI { event.inventory.items.values.forEach { itemStack -> val pet = getPetData(itemStack) ?: return@forEach - if(!pet.active) return@forEach - - changePet(pet) + if(pet.active) changePet(pet) } } diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/events/mythological/AnnounceRareDrops.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/events/mythological/AnnounceRareDrops.kt index fa42ae3e..d7ae62af 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/events/mythological/AnnounceRareDrops.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/events/mythological/AnnounceRareDrops.kt @@ -32,8 +32,8 @@ object AnnounceRareDrops { private fun onSlotUpdate(event: InventoryEvents.SlotUpdate) { if(!enabled) return - val itemStack = event.stack - val item = itemStack.asSkyBlockItem ?: return + val stack = event.stack + val item = stack.asSkyBlockItem ?: return if(item.id !in rareDrops) return item.timestamp?.let { if(it.elapsedSince() > 3.seconds) return } ?: return @@ -45,7 +45,7 @@ object AnnounceRareDrops { val text = buildText { append(tr("nobaaddons.chat.rareDrop", "RARE DROP!").formatted(Formatting.GOLD, Formatting.BOLD)) append(" ") - append(itemStack.name) + append(stack.name) } ChatUtils.addMessage(text, prefix = false) From 67ea968f4524e6c4b43f736ba21f1f0e55a37888 Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Mon, 12 May 2025 20:26:08 +0300 Subject: [PATCH 04/14] my comments are something like it's obvious --- .../me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index 9cb3a243..3ef05b07 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -148,7 +148,6 @@ object ItemPickupLog { } } - // Add only removed items that weren't also added for((name, removeEntry) in removedItems) { if(name !in addedItems) { add(buildText { From 65e97e4221069964d53556c2192625edddd98fa0 Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Mon, 12 May 2025 22:34:41 +0300 Subject: [PATCH 05/14] reviews --- src/main/kotlin/me/nobaboy/nobaaddons/NobaAddons.kt | 5 +---- src/main/kotlin/me/nobaboy/nobaaddons/api/InventoryAPI.kt | 2 +- .../me/nobaboy/nobaaddons/config/configs/InventoryConfig.kt | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/NobaAddons.kt b/src/main/kotlin/me/nobaboy/nobaaddons/NobaAddons.kt index 39b0a4fb..d21cffae 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/NobaAddons.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/NobaAddons.kt @@ -155,10 +155,6 @@ object NobaAddons : ClientModInitializer { SWikiCommand.init() /* endregion */ - /* region User Interface */ - ItemPickupLog.init() - /* endregion */ - /* region Features */ // region Visuals EtherwarpOverlay.init() @@ -168,6 +164,7 @@ object NobaAddons : ClientModInitializer { // region Inventory EnchantmentTooltips.init() ISlotInfo.init() + ItemPickupLog.init() // endregion // region Events diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/api/InventoryAPI.kt b/src/main/kotlin/me/nobaboy/nobaaddons/api/InventoryAPI.kt index 0f2ccffb..f6406657 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/api/InventoryAPI.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/api/InventoryAPI.kt @@ -75,5 +75,5 @@ object InventoryAPI { InventoryEvents.CLOSE.dispatch(InventoryEvents.Close(sameName)) } - data class Screen(val id: Int, val title: String) + private data class Screen(val id: Int, val title: String) } \ No newline at end of file diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/config/configs/InventoryConfig.kt b/src/main/kotlin/me/nobaboy/nobaaddons/config/configs/InventoryConfig.kt index 3f89ae5e..7aa4e784 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/config/configs/InventoryConfig.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/config/configs/InventoryConfig.kt @@ -53,7 +53,7 @@ class InventoryConfig { class ItemPickupLog { var enabled = false - var compactLines = false + var compactLines = true var timeoutSeconds = 5 } } \ No newline at end of file From 468a93cc74c1ca2e6404072bf5fd60eb18936c8e Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Mon, 12 May 2025 22:50:43 +0300 Subject: [PATCH 06/14] =?UTF-8?q?nobaboy=20=E2=80=94=2022:41=20"you=20gott?= =?UTF-8?q?a=20realise=20it=20takes=20me=20a=20minute=20to=20figure=20out?= =?UTF-8?q?=20what=20to=20type=20in=20before=20you=20come=20in=20and=20cha?= =?UTF-8?q?nge=20it"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../me/nobaboy/nobaaddons/config/categories/InventoryCategory.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/config/categories/InventoryCategory.kt b/src/main/kotlin/me/nobaboy/nobaaddons/config/categories/InventoryCategory.kt index b59c42d6..0d58574e 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/config/categories/InventoryCategory.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/config/categories/InventoryCategory.kt @@ -206,6 +206,7 @@ object InventoryCategory { } add({ inventory.itemPickupLog::compactLines }) { name = tr("nobaaddons.config.inventory.itemPickupLog.compactLines", "Compact Lines") + descriptionText = tr("nobaaddons.config.inventory.itemPickupLog.compactLines.tooltip", "Shows a single line with the total difference, instead of displaying the added/removed item counts separately") require { option(enabled) } booleanController() } From 8328c3df5b5389e84aa729e57885efae8793137b Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Mon, 12 May 2025 23:16:58 +0300 Subject: [PATCH 07/14] fix 1.21.5 build --- .../nobaaddons/features/inventory/ItemPickupLog.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index 9b193a9c..022b3f51 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -1,5 +1,9 @@ package me.nobaboy.nobaaddons.features.inventory +//? if >=1.21.5 { +/*import me.nobaboy.nobaaddons.mixins.accessors.PlayerInventoryAccessor +*///?} + import me.nobaboy.nobaaddons.api.skyblock.SkyBlockAPI import me.nobaboy.nobaaddons.config.NobaConfig import me.nobaboy.nobaaddons.config.UISettings @@ -68,7 +72,7 @@ object ItemPickupLog { val delta = (current[name] ?: 0) - (previous[name] ?: 0) if(delta == 0) continue - val map = if (delta > 0) addedItems else removedItems + val map = if(delta > 0) addedItems else removedItems val previousChange = map[name]?.change ?: 0 map[name] = ItemEntry(previousChange + abs(delta)) } @@ -76,7 +80,7 @@ object ItemPickupLog { private fun PlayerInventory.nameToCount(): Map = buildMap { //? if >=1.21.5 { - /*val main = (this@itemNamesToCount as PlayerInventoryAccessor).main + /*val main = (this@nameToCount as PlayerInventoryAccessor).main *///?} main.forEachIndexed { slot, stack -> @@ -117,9 +121,9 @@ object ItemPickupLog { return buildList { if(config.compactLines) { - val allNames = (addedItems.keys + removedItems.keys).toSet() + val names = (addedItems.keys + removedItems.keys).toSet() - for (name in allNames) { + for(name in names) { val added = addedItems[name]?.change ?: 0 val removed = removedItems[name]?.change ?: 0 From bdad62f5ab080406055d26a8a020fcf58dd2cf93 Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Mon, 12 May 2025 23:51:37 +0300 Subject: [PATCH 08/14] Split compact and split lines into their own functions --- .../features/inventory/ItemPickupLog.kt | 89 +++++++++---------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index 022b3f51..fc31ffcf 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -114,56 +114,48 @@ object ItemPickupLog { return this } - // TODO wtf is this, split into 2 functions and call whichever based on config.compactLines - private fun buildDisplayLines(): List { - addedItems.values.removeIf { it.expired } - removedItems.values.removeIf { it.expired } - - return buildList { - if(config.compactLines) { - val names = (addedItems.keys + removedItems.keys).toSet() - - for(name in names) { - val added = addedItems[name]?.change ?: 0 - val removed = removedItems[name]?.change ?: 0 - - val delta = added - removed - if(delta == 0) continue - - add(buildText { - literal(if(delta > 0) "+${delta.addSeparators()}x " else "-${(-delta).addSeparators()}x ") { - if(delta > 0) green() else red() - } - append(name) - }) - } - } else { - for((name, addEntry) in addedItems) { - add(buildText { - literal("+${addEntry.change.addSeparators()}x ") { green() } - append(name) - }) - - removedItems[name]?.let { removeEntry -> - add(buildText { - literal("-${removeEntry.change.addSeparators()}x ") { red() } - append(name) - }) - } - } + private fun compileCompactLines(): List = buildList { + val names = addedItems.keys + removedItems.keys + + names.forEach { name -> + val added = addedItems[name]?.change ?: 0 + val removed = removedItems[name]?.change ?: 0 - for((name, removeEntry) in removedItems) { - if(name !in addedItems) { - add(buildText { - literal("-${removeEntry.change.addSeparators()}x ") { red() } - append(name) - }) - } + val delta = added - removed + if(delta == 0) return@forEach + + add(buildText { + val symbol = if(delta > 0) "+" else "" + literal("$symbol${delta.addSeparators()}x ") { + if(delta > 0) green() else red() } - } + append(name) + }) } } + private fun compileSplitLines(): List = buildList { + addedItems.forEach { (name, entry) -> + add(buildText { + literal("+${entry.change.addSeparators()}x ") { green() } + append(name) + }) + + removedItems[name]?.let { entry -> + add(buildText { + literal("-${entry.change.addSeparators()}x ") { red() } + append(name) + }) + } + } + + removedItems.filterKeys { it !in addedItems }.forEach { (name, entry) -> + add(buildText { + literal("-${entry.change.addSeparators()}x ") { red() } + append(name) + }) + } + } private fun reset() { items.clear() @@ -180,7 +172,12 @@ object ItemPickupLog { override val maxScale: Float = 1f override fun renderText(context: DrawContext) { - renderLines(context, buildDisplayLines()) + // TODO could this be in the onTick or is there a slight chance I get a CME + addedItems.values.removeIf { it.expired } + removedItems.values.removeIf { it.expired } + + val lines = if(config.compactLines) compileCompactLines() else compileSplitLines() + renderLines(context, lines) } } From 954b83b329208f785f9b1a38820a7d866528a465 Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Tue, 13 May 2025 00:56:58 +0300 Subject: [PATCH 09/14] Use `Object2ObjectArrayMap` and prevent a possible CME once the threads are separated --- .../features/inventory/ItemPickupLog.kt | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index fc31ffcf..d034bd85 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -4,6 +4,7 @@ package me.nobaboy.nobaaddons.features.inventory /*import me.nobaboy.nobaaddons.mixins.accessors.PlayerInventoryAccessor *///?} +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import me.nobaboy.nobaaddons.api.skyblock.SkyBlockAPI import me.nobaboy.nobaaddons.config.NobaConfig import me.nobaboy.nobaaddons.config.UISettings @@ -33,11 +34,11 @@ object ItemPickupLog { private val config get() = NobaConfig.inventory.itemPickupLog private val enabled: Boolean get() = config.enabled && SkyBlockAPI.inSkyBlock - private val items = mutableMapOf() + private val items = Object2ObjectArrayMap() private var suppressTime = Timestamp.distantPast() - private val addedItems = mutableMapOf() - private val removedItems = mutableMapOf() + private val addedItems = Object2ObjectArrayMap() + private val removedItems = Object2ObjectArrayMap() init { SkyBlockEvents.ISLAND_CHANGE.register { reset() } @@ -47,8 +48,11 @@ object ItemPickupLog { private fun onTick(event: TickEvents.Tick) { if(!enabled) return - if(event.client.currentScreen != null) return + addedItems.values.removeIf { it.expired } + removedItems.values.removeIf { it.expired } + + if(event.client.currentScreen != null) return val player = event.client.player ?: return val newItems = player.inventory.nameToCount() @@ -114,14 +118,14 @@ object ItemPickupLog { return this } - private fun compileCompactLines(): List = buildList { - val names = addedItems.keys + removedItems.keys + private fun compileCompactLines( + added: Map, + removed: Map, + ): List = buildList { + val names = added.keys + removed.keys names.forEach { name -> - val added = addedItems[name]?.change ?: 0 - val removed = removedItems[name]?.change ?: 0 - - val delta = added - removed + val delta = (added[name]?.change ?: 0) - (removed[name]?.change ?: 0) if(delta == 0) return@forEach add(buildText { @@ -134,14 +138,17 @@ object ItemPickupLog { } } - private fun compileSplitLines(): List = buildList { - addedItems.forEach { (name, entry) -> + private fun compileSplitLines( + added: Map, + removed: Map, + ): List = buildList { + added.forEach { (name, entry) -> add(buildText { literal("+${entry.change.addSeparators()}x ") { green() } append(name) }) - removedItems[name]?.let { entry -> + removed[name]?.let { entry -> add(buildText { literal("-${entry.change.addSeparators()}x ") { red() } append(name) @@ -149,7 +156,7 @@ object ItemPickupLog { } } - removedItems.filterKeys { it !in addedItems }.forEach { (name, entry) -> + removed.filterKeys { it !in added }.forEach { (name, entry) -> add(buildText { literal("-${entry.change.addSeparators()}x ") { red() } append(name) @@ -172,11 +179,15 @@ object ItemPickupLog { override val maxScale: Float = 1f override fun renderText(context: DrawContext) { - // TODO could this be in the onTick or is there a slight chance I get a CME - addedItems.values.removeIf { it.expired } - removedItems.values.removeIf { it.expired } + val added = addedItems.clone() + val removed = removedItems.clone() + + val lines = if(config.compactLines) { + compileCompactLines(added, removed) + } else { + compileSplitLines(added, removed) + } - val lines = if(config.compactLines) compileCompactLines() else compileSplitLines() renderLines(context, lines) } } From 8cbc22b203d0aacb942821b8d1c276cd7c7528c1 Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Tue, 13 May 2025 00:57:25 +0300 Subject: [PATCH 10/14] this makes more sense to me --- .../me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index d034bd85..c165660e 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -35,11 +35,12 @@ object ItemPickupLog { private val enabled: Boolean get() = config.enabled && SkyBlockAPI.inSkyBlock private val items = Object2ObjectArrayMap() - private var suppressTime = Timestamp.distantPast() private val addedItems = Object2ObjectArrayMap() private val removedItems = Object2ObjectArrayMap() + private var suppressTime = Timestamp.distantPast() + init { SkyBlockEvents.ISLAND_CHANGE.register { reset() } TickEvents.TICK.register(this::onTick) From 4e51f42cb7aa1ab8805c12e05353de517ba80cc0 Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Tue, 13 May 2025 01:22:07 +0300 Subject: [PATCH 11/14] combine both added and removed into `ItemEntry` under 1 array --- .../features/inventory/ItemPickupLog.kt | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index c165660e..3d6acc60 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -24,7 +24,6 @@ import net.minecraft.client.gui.DrawContext import net.minecraft.entity.player.PlayerInventory import net.minecraft.text.Text import net.minecraft.util.Formatting -import kotlin.math.abs import kotlin.time.Duration.Companion.seconds object ItemPickupLog { @@ -35,9 +34,7 @@ object ItemPickupLog { private val enabled: Boolean get() = config.enabled && SkyBlockAPI.inSkyBlock private val items = Object2ObjectArrayMap() - - private val addedItems = Object2ObjectArrayMap() - private val removedItems = Object2ObjectArrayMap() + private val itemLog = Object2ObjectArrayMap() private var suppressTime = Timestamp.distantPast() @@ -50,8 +47,7 @@ object ItemPickupLog { private fun onTick(event: TickEvents.Tick) { if(!enabled) return - addedItems.values.removeIf { it.expired } - removedItems.values.removeIf { it.expired } + itemLog.values.removeIf { it.expired } if(event.client.currentScreen != null) return val player = event.client.player ?: return @@ -77,9 +73,9 @@ object ItemPickupLog { val delta = (current[name] ?: 0) - (previous[name] ?: 0) if(delta == 0) continue - val map = if(delta > 0) addedItems else removedItems - val previousChange = map[name]?.change ?: 0 - map[name] = ItemEntry(previousChange + abs(delta)) + val entry = itemLog.getOrPut(name) { ItemEntry() } + if(delta > 0) entry.added += delta else entry.removed += -delta + entry.timestamp = Timestamp.now() } } @@ -126,7 +122,7 @@ object ItemPickupLog { val names = added.keys + removed.keys names.forEach { name -> - val delta = (added[name]?.change ?: 0) - (removed[name]?.change ?: 0) + val delta = (added[name]?.added ?: 0) - (removed[name]?.removed ?: 0) if(delta == 0) return@forEach add(buildText { @@ -145,13 +141,13 @@ object ItemPickupLog { ): List = buildList { added.forEach { (name, entry) -> add(buildText { - literal("+${entry.change.addSeparators()}x ") { green() } + literal("+${entry.added.addSeparators()}x ") { green() } append(name) }) removed[name]?.let { entry -> add(buildText { - literal("-${entry.change.addSeparators()}x ") { red() } + literal("-${entry.removed.addSeparators()}x ") { red() } append(name) }) } @@ -159,7 +155,7 @@ object ItemPickupLog { removed.filterKeys { it !in added }.forEach { (name, entry) -> add(buildText { - literal("-${entry.change.addSeparators()}x ") { red() } + literal("-${entry.removed.addSeparators()}x ") { red() } append(name) }) } @@ -167,8 +163,7 @@ object ItemPickupLog { private fun reset() { items.clear() - addedItems.clear() - removedItems.clear() + itemLog.clear() suppressTime = Timestamp.now() } @@ -180,8 +175,10 @@ object ItemPickupLog { override val maxScale: Float = 1f override fun renderText(context: DrawContext) { - val added = addedItems.clone() - val removed = removedItems.clone() + val itemLog = itemLog.clone() + + val added = itemLog.filterValues { it.added > 0 } + val removed = itemLog.filterValues { it.removed > 0 } val lines = if(config.compactLines) { compileCompactLines(added, removed) @@ -194,7 +191,8 @@ object ItemPickupLog { } private data class ItemEntry( - var change: Int = 0, + var added: Int = 0, + var removed: Int = 0, var timestamp: Timestamp = Timestamp.now(), ) { val expired: Boolean From b7ae7dd868123637a092efdc8dec4a55b0ec1baa Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Tue, 13 May 2025 04:04:01 +0300 Subject: [PATCH 12/14] reviews --- .../features/inventory/ItemPickupLog.kt | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index 3d6acc60..b1d9bb73 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -60,7 +60,8 @@ object ItemPickupLog { items[name] = items.getOrDefault(name, 0) + count } - // this check is here solely to update items because it's empty to start with + // ignore item changes for ~2s when switching servers, as your inventory is + // initially empty when loading in if(suppressTime.elapsedSince() < 2.seconds) return detectItemChanges(items, oldItems) } @@ -95,7 +96,6 @@ object ItemPickupLog { // offHand.firstOrNull()?.let { merge(name, it.count, Int::plus) } } - // TODO maybe clean this up, can't get rid of it cuz we need to remove the count either way private fun Text.removeMerchantCount(): Text { if(siblings.size <= 1) return this val last = siblings.last() @@ -139,11 +139,15 @@ object ItemPickupLog { added: Map, removed: Map, ): List = buildList { - added.forEach { (name, entry) -> - add(buildText { - literal("+${entry.added.addSeparators()}x ") { green() } - append(name) - }) + val names = added.keys + removed.keys + + names.forEach { name -> + added[name]?.let { entry -> + add(buildText { + literal("+${entry.added.addSeparators()}x ") { green() } + append(name) + }) + } removed[name]?.let { entry -> add(buildText { @@ -152,13 +156,6 @@ object ItemPickupLog { }) } } - - removed.filterKeys { it !in added }.forEach { (name, entry) -> - add(buildText { - literal("-${entry.removed.addSeparators()}x ") { red() } - append(name) - }) - } } private fun reset() { From 3887825abf522be45dda82dcb445b729a3243ec7 Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Wed, 14 May 2025 02:02:35 +0300 Subject: [PATCH 13/14] fix offhand for 1.21.5 and below --- repo | 2 +- .../mixins/accessors/PlayerInventoryAccessor.java | 7 ++++--- .../nobaaddons/commands/adapters/FormattingHandler.kt | 3 --- src/main/kotlin/me/nobaboy/nobaaddons/core/Skill.kt | 3 --- .../nobaaddons/features/inventory/ItemPickupLog.kt | 11 +++++++++-- .../nobaaddons/features/ui/infobox/migrations.kt | 1 - 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/repo b/repo index 9821630b..b9f4ebad 160000 --- a/repo +++ b/repo @@ -1 +1 @@ -Subproject commit 9821630b9c00f21004eeb48d8933cbe8e982c0ce +Subproject commit b9f4ebad697b0e10f74e961e4a4e31f23dcc6115 diff --git a/src/main/java/me/nobaboy/nobaaddons/mixins/accessors/PlayerInventoryAccessor.java b/src/main/java/me/nobaboy/nobaaddons/mixins/accessors/PlayerInventoryAccessor.java index d6886b4c..c25f425d 100644 --- a/src/main/java/me/nobaboy/nobaaddons/mixins/accessors/PlayerInventoryAccessor.java +++ b/src/main/java/me/nobaboy/nobaaddons/mixins/accessors/PlayerInventoryAccessor.java @@ -1,7 +1,8 @@ package me.nobaboy.nobaaddons.mixins.accessors; //? if >=1.21.5 { -/*import net.minecraft.entity.player.PlayerInventory; +/*import net.minecraft.entity.EntityEquipment; +import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.collection.DefaultedList; import org.spongepowered.asm.mixin.Mixin; @@ -9,7 +10,7 @@ @Mixin(PlayerInventory.class) public interface PlayerInventoryAccessor { - @Accessor - DefaultedList getMain(); + @Accessor DefaultedList getMain(); + @Accessor EntityEquipment getEquipment(); } *///?} diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/commands/adapters/FormattingHandler.kt b/src/main/kotlin/me/nobaboy/nobaaddons/commands/adapters/FormattingHandler.kt index 40785a00..81ef4bc8 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/commands/adapters/FormattingHandler.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/commands/adapters/FormattingHandler.kt @@ -6,10 +6,7 @@ import dev.celestialfault.commander.ArgumentHandler import me.nobaboy.nobaaddons.commands.impl.CommandUtil.getArgument import me.nobaboy.nobaaddons.utils.JavaUtils import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource -import net.minecraft.command.CommandSource -import net.minecraft.command.argument.EnumArgumentType import net.minecraft.util.Formatting -import net.minecraft.util.StringIdentifiable import kotlin.reflect.KParameter import kotlin.reflect.full.hasAnnotation diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/core/Skill.kt b/src/main/kotlin/me/nobaboy/nobaaddons/core/Skill.kt index 7e73f05f..33900556 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/core/Skill.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/core/Skill.kt @@ -1,9 +1,6 @@ package me.nobaboy.nobaaddons.core -import com.mojang.brigadier.context.CommandContext import com.mojang.serialization.Codec -import net.minecraft.command.CommandSource -import net.minecraft.command.argument.EnumArgumentType import net.minecraft.util.StringIdentifiable enum class Skill(val isCosmetic: Boolean = false, val includeInSkillAverage: Boolean = !isCosmetic) : StringIdentifiable { diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index b1d9bb73..7ace538a 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -2,6 +2,7 @@ package me.nobaboy.nobaaddons.features.inventory //? if >=1.21.5 { /*import me.nobaboy.nobaaddons.mixins.accessors.PlayerInventoryAccessor +import net.minecraft.entity.EquipmentSlot *///?} import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap @@ -83,6 +84,7 @@ object ItemPickupLog { private fun PlayerInventory.nameToCount(): Map = buildMap { //? if >=1.21.5 { /*val main = (this@nameToCount as PlayerInventoryAccessor).main + val equipment = (this@nameToCount as PlayerInventoryAccessor).equipment *///?} main.forEachIndexed { slot, stack -> @@ -92,8 +94,13 @@ object ItemPickupLog { merge(name, stack.count, Int::plus) } - // TODO fix for 1.21.5 and remove merchant count from name just in case -// offHand.firstOrNull()?.let { merge(name, it.count, Int::plus) } + //? if >=1.21.5 { + /*equipment.get(EquipmentSlot.OFFHAND) + *///?} else { + offHand.firstOrNull() + //?} + ?.takeIf { !it.isEmpty } + ?.let { merge(it.name, it.count, Int::plus) } } private fun Text.removeMerchantCount(): Text { diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/ui/infobox/migrations.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/ui/infobox/migrations.kt index 7ddef57e..e5392928 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/ui/infobox/migrations.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/ui/infobox/migrations.kt @@ -10,7 +10,6 @@ import dev.celestialfault.histoire.migrations.rename import kotlinx.serialization.json.JsonPrimitive import me.nobaboy.nobaaddons.config.util.mapAndRename import me.nobaboy.nobaaddons.config.util.moveTo -import kotlin.collections.set internal val migrations = Migrations("configVersion") { add(::`001_uiElementRefactor`) From 0d4ddfef1098c9465bf42086c2e00750026e4c1e Mon Sep 17 00:00:00 2001 From: nobaboy <84668101+nobaboy@users.noreply.github.com> Date: Wed, 14 May 2025 02:12:47 +0300 Subject: [PATCH 14/14] thanks intellij but I want it like this. --- .../me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt index 7ace538a..2a9708a6 100644 --- a/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt +++ b/src/main/kotlin/me/nobaboy/nobaaddons/features/inventory/ItemPickupLog.kt @@ -67,7 +67,7 @@ object ItemPickupLog { detectItemChanges(items, oldItems) } - // TODO either remove current and just use items straight out or suppress this + @Suppress("SameParameterValue") // this is intentional because I feel like it's easier to read private fun detectItemChanges(current: Map, previous: Map) { val names = current.keys + previous.keys