From e0fc780a007acbc4c74520c0780a83edfaf477d2 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Fri, 17 Feb 2023 01:12:06 +0100 Subject: More Garden features around Visitor. --- .../java/at/hannibal2/skyhanni/SkyHanniMod.java | 2 + .../at/hannibal2/skyhanni/config/Features.java | 5 + .../hannibal2/skyhanni/config/features/Garden.java | 29 +++ .../features/garden/GardenVisitorFeatures.kt | 221 +++++++++++++++++++++ .../skyhanni/features/garden/SkyMartBestProfit.kt | 21 +- .../java/at/hannibal2/skyhanni/utils/NEUItems.kt | 21 ++ 6 files changed, 289 insertions(+), 10 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/garden/GardenVisitorFeatures.kt (limited to 'src') diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java index 998185755..3266af83c 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java @@ -23,6 +23,7 @@ import at.hannibal2.skyhanni.features.event.diana.GriffinBurrowHelper; import at.hannibal2.skyhanni.features.event.diana.GriffinBurrowParticleFinder; import at.hannibal2.skyhanni.features.event.diana.SoopyGuessBurrow; import at.hannibal2.skyhanni.features.fishing.*; +import at.hannibal2.skyhanni.features.garden.GardenVisitorFeatures; import at.hannibal2.skyhanni.features.garden.SkyMartBestProfit; import at.hannibal2.skyhanni.features.inventory.*; import at.hannibal2.skyhanni.features.itemabilities.FireVeilWandParticles; @@ -197,6 +198,7 @@ public class SkyHanniMod { loadModule(new ParticleHider()); loadModule(new MiscFeatures()); loadModule(new SkyMartBestProfit()); + loadModule(new GardenVisitorFeatures()); Commands.INSTANCE.init(); diff --git a/src/main/java/at/hannibal2/skyhanni/config/Features.java b/src/main/java/at/hannibal2/skyhanni/config/Features.java index 633bc66c6..13ebf5106 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/Features.java +++ b/src/main/java/at/hannibal2/skyhanni/config/Features.java @@ -141,6 +141,11 @@ public class Features extends Config { editOverlay(activeConfigCategory, 200, 16, garden.skyMartCopperPricePos); return; } + + if (runnableId.equals("visitorHelper")) { + editOverlay(activeConfigCategory, 200, 16, garden.visitorHelperPos); + return; + } } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java index 9dec32d73..d5344900b 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java @@ -22,4 +22,33 @@ public class Garden { @ConfigEditorButton(runnableId = "skyMartCopperPrice", buttonText = "Edit") @ConfigAccordionId(id = 0) public Position skyMartCopperPricePos = new Position(44, -108, false, true); + + @Expose + @ConfigOption(name = "Visitor Helper", desc = "") + @ConfigEditorAccordion(id = 1) + public boolean visitorHelper = false; + + @Expose + @ConfigOption(name = "Visitor Display", desc = "Show all items needed for the visitors.") + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean visitorHelperDisplay = true; + + @Expose + @ConfigOption(name = "Visitor Helper Position", desc = "") + @ConfigEditorButton(runnableId = "visitorHelper", buttonText = "Edit") + @ConfigAccordionId(id = 1) + public Position visitorHelperPos = new Position(0, 0, false, true); + + @Expose + @ConfigOption(name = "Highlight Ready", desc = "Highlight the visitor when the required items are in the inventory.") + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean visitorHelperHighlightReady = true; + + @Expose + @ConfigOption(name = "Show Price", desc = "Show the bazaar price of the items required for the visitors.") + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean visitorHelperShowPrice = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenVisitorFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenVisitorFeatures.kt new file mode 100644 index 000000000..513c91425 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenVisitorFeatures.kt @@ -0,0 +1,221 @@ +package at.hannibal2.skyhanni.features.garden + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.InventoryOpenEvent +import at.hannibal2.skyhanni.events.PacketEvent +import at.hannibal2.skyhanni.events.withAlpha +import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper +import at.hannibal2.skyhanni.utils.* +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import net.minecraft.client.Minecraft +import net.minecraft.entity.EntityLivingBase +import net.minecraft.network.play.client.C02PacketUseEntity +import net.minecraft.network.play.server.S13PacketDestroyEntities +import net.minecraftforge.client.event.RenderGameOverlayEvent +import net.minecraftforge.event.entity.player.ItemTooltipEvent +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import java.util.regex.Pattern + +class GardenVisitorFeatures { + + private val pattern = Pattern.compile("(.*)§8x(.*)") + private val visitors = mutableMapOf() + private val display = mutableListOf() + private var lastClickedNpc = 0 + private var nearby = false + + @SubscribeEvent + fun onChatPacket(event: InventoryOpenEvent) { + if (!isEnabled()) return + if (!SkyHanniMod.feature.garden.visitorHelperDisplay && + !SkyHanniMod.feature.garden.visitorHelperHighlightReady + ) return + + val npcItem = event.inventory.items[13] ?: return + val lore = npcItem.getLore() + var isVisitor = false + if (lore.size == 4) { + val line = lore[3] + if (line.startsWith("§7Offers Accepted: §a")) { + isVisitor = true + } + } + if (!isVisitor) return + + val offerItem = event.inventory.items[29] ?: return + if (offerItem.name != "§aAccept Offer") return + + val visitor = Visitor(lastClickedNpc) + for (line in offerItem.getLore()) { + if (line == "§7Items Required:") continue + if (line.isEmpty()) break + + val matcher = pattern.matcher(line) + if (matcher.matches()) { + val itemName = matcher.group(1).trim() + val amount = matcher.group(2).toInt() + visitor.items[itemName] = amount + } + } + + val visitorName = npcItem.name!! + visitors[visitorName] = visitor + + update() + } + + private fun update() { + display.clear() + + val requiredItems = mutableMapOf() + for ((_, visitor) in visitors) { + for ((itemName, amount) in visitor.items) { + val old = requiredItems.getOrDefault(itemName, 0) + requiredItems[itemName] = old + amount + } + } + if (requiredItems.isEmpty()) return + + display.add("Visitors need:") + for ((name, amount) in requiredItems) { + display.add(" -$name §8x$amount") + } + } + + var tick = 0 + + @SubscribeEvent(priority = EventPriority.LOW) + fun onTooltip(event: ItemTooltipEvent) { + if (!isEnabled()) return + if (!nearby) return + if (!SkyHanniMod.feature.garden.visitorHelperShowPrice) return + + val name = event.itemStack.name ?: return + if (name != "§aAccept Offer") return + + var i = 0 + val list = event.toolTip + var totalPrice = 0.0 + var amountDifferentItems = 0 + for (l in list) { + val line = l.substring(4) + if (line == "") { + if (amountDifferentItems > 1) { + val format = NumberUtil.format(totalPrice) + list[1] = list[1] + "$line §f(§6$format§f)" + } + break + } + + if (i > 1) { + val matcher = pattern.matcher(line) + if (matcher.matches()) { + val itemName = matcher.group(1).trim() + val amount = matcher.group(2).toInt() + + val internalName = NEUItems.getInternalNameByName(itemName) + val auctionManager = NotEnoughUpdates.INSTANCE.manager.auctionManager + val lowestBin = auctionManager.getBazaarOrBin(internalName, false) + val price = lowestBin * amount + totalPrice += price + val format = NumberUtil.format(price) + list[i] = "$line §f(§6$format§f)" + amountDifferentItems++ + } + } + i++ + } + } + + @SubscribeEvent + fun onTick(event: TickEvent.ClientTickEvent) { + if (!isEnabled()) return + if (!SkyHanniMod.feature.garden.visitorHelperDisplay && + !SkyHanniMod.feature.garden.visitorHelperHighlightReady && + !SkyHanniMod.feature.garden.visitorHelperShowPrice + ) return + + if (tick++ % 60 == 0) { + check() + } + } + + private fun check() { + nearby = LocationUtils.playerLocation().distance(LorenzVec(8.4, 72.0, -14.1)) < 10 + + if (nearby && SkyHanniMod.feature.garden.visitorHelperHighlightReady) { + checkVisitorsReady() + } + } + + private fun checkVisitorsReady() { + for (visitor in visitors.values) { + var ready = true + for ((name, need) in visitor.items) { + val cleanName = name.removeColor() + val having = InventoryUtils.countItemsInLowerInventory { it.name?.contains(cleanName) ?: false } + if (having < need) { + ready = false + } + } + + if (ready) { + val world = Minecraft.getMinecraft().theWorld + val entity = world.getEntityByID(visitor.entityId) + if (entity is EntityLivingBase) { + val color = LorenzColor.GREEN.toColor().withAlpha(120) + RenderLivingEntityHelper.setEntityColor(entity, color) + { SkyHanniMod.feature.garden.visitorHelperHighlightReady } + } + } + } + } + + @SubscribeEvent + fun onReceiveEvent(event: PacketEvent.ReceiveEvent) { + val packet = event.packet + if (packet is S13PacketDestroyEntities) { + for (entityID in packet.entityIDs) { + for ((name, visitor) in visitors.toMutableMap()) { + if (visitor.entityId == entityID) { + visitors.remove(name) + update() + } + } + } + } + } + + @SubscribeEvent + fun onSendEvent(event: PacketEvent.SendEvent) { + val packet = event.packet + if (packet is C02PacketUseEntity) { + val theWorld = Minecraft.getMinecraft().theWorld + val entity = packet.getEntityFromWorld(theWorld) + val entityId = entity.entityId + + lastClickedNpc = entityId + } + } + + @SubscribeEvent + fun onRenderOverlay(event: RenderGameOverlayEvent.Post) { + if (event.type != RenderGameOverlayEvent.ElementType.ALL) return + if (!isEnabled()) return + if (!SkyHanniMod.feature.garden.visitorHelperDisplay) return + if (!nearby) return + + SkyHanniMod.feature.garden.visitorHelperPos.renderStrings(display) + } + + class Visitor(val entityId: Int, val items: MutableMap = mutableMapOf()) + + private fun isEnabled() = LorenzUtils.inSkyBlock && LorenzUtils.skyBlockIsland == IslandType.GARDEN +} \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartBestProfit.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartBestProfit.kt index 8e9cc3dfa..369765c5d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartBestProfit.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartBestProfit.kt @@ -24,9 +24,7 @@ class SkyMartBestProfit { @SubscribeEvent fun onChatPacket(event: InventoryOpenEvent) { - if (!LorenzUtils.inSkyBlock) return - if (!SkyHanniMod.feature.garden.skyMartCopperPrice) return - if (LorenzUtils.skyBlockIsland != IslandType.GARDEN) return + if (!isEnabled()) return val inventory = event.inventory if (inventory.title != "SkyMart") return @@ -55,14 +53,14 @@ class SkyMartBestProfit { name = "§9Sunder I" } - val pair = Pair("$name§f:", "§6§l$perFormat §f(§6$priceFormat coins §f/ §c$amountFormat copper§f)") + val pair = Pair("$name§f:", "§6§l$perFormat §f(§6$priceFormat §f/ §c$amountFormat copper§f)") priceMap[pair] = factor } } display.clear() - display.add("Coins per §ccopper") + display.add("Coins per §ccopper§f:") display.add(" ") val keys = priceMap.sortedDesc().keys @@ -85,10 +83,13 @@ class SkyMartBestProfit { @SubscribeEvent fun onBackgroundDraw(event: GuiScreenEvent.BackgroundDrawnEvent) { - if (!LorenzUtils.inSkyBlock) return - if (!SkyHanniMod.feature.garden.skyMartCopperPrice) return - if (LorenzUtils.skyBlockIsland != IslandType.GARDEN) return - - SkyHanniMod.feature.garden.skyMartCopperPricePos.renderStrings(display) + if (isEnabled()) { + SkyHanniMod.feature.garden.skyMartCopperPricePos.renderStrings(display) + } } + + private fun isEnabled() = + LorenzUtils.inSkyBlock && + SkyHanniMod.feature.garden.skyMartCopperPrice && + LorenzUtils.skyBlockIsland == IslandType.GARDEN } \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt index 46c9c6fea..8c127fac8 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.utils +import at.hannibal2.skyhanni.utils.StringUtils.removeColor import io.github.moulberry.notenoughupdates.NotEnoughUpdates import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.renderer.GlStateManager @@ -9,6 +10,26 @@ import net.minecraft.item.ItemStack object NEUItems { private val itemCache = mutableMapOf() + private val itemNameCache = mutableMapOf() // display name -> internal name + + fun getInternalNameByName(rawName: String): String? { + val itemName = rawName.removeColor() + if (itemNameCache.containsKey(itemName)) { + return itemNameCache[itemName] + } + val manager = NotEnoughUpdates.INSTANCE.manager + for ((internalId, b) in manager.itemInformation) { + if (b.has("displayname")) { + val name = b.get("displayname").asString + if (name.contains(itemName)) { + itemNameCache[itemName] = internalId + return internalId + } + } + } + + return null + } fun readItemFromRepo(internalName: String): ItemStack { if (itemCache.contains(internalName)) { -- cgit