aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni
diff options
context:
space:
mode:
authorThunderblade73 <85900443+Thunderblade73@users.noreply.github.com>2023-11-30 11:53:58 +0100
committerGitHub <noreply@github.com>2023-11-30 11:53:58 +0100
commit715d27d77b3c381cffb54f0213f82b07ce6b7286 (patch)
treee9a45529f216a57f1fc6b130e639341b4ed2b78a /src/main/java/at/hannibal2/skyhanni
parenta33686f0bcf9828c0bdd1568724fe6b8826b7027 (diff)
downloadskyhanni-715d27d77b3c381cffb54f0213f82b07ce6b7286.tar.gz
skyhanni-715d27d77b3c381cffb54f0213f82b07ce6b7286.tar.bz2
skyhanni-715d27d77b3c381cffb54f0213f82b07ce6b7286.zip
Feature: Minion Xp Calculator (#639)
Shows how much skill experience you will get when picking up items from the minion storage. #639
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/minion/MinionsConfig.java6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/MinionXPJson.java10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/MinionOpenEvent.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt22
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/minion/MinionXp.kt194
6 files changed, 234 insertions, 4 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
index 4d18ecdf0..94e763f3b 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
@@ -209,6 +209,7 @@ import at.hannibal2.skyhanni.features.mining.crystalhollows.CrystalHollowsNamesI
import at.hannibal2.skyhanni.features.mining.powdertracker.PowderTracker
import at.hannibal2.skyhanni.features.minion.MinionCollectLogic
import at.hannibal2.skyhanni.features.minion.MinionFeatures
+import at.hannibal2.skyhanni.features.minion.MinionXp
import at.hannibal2.skyhanni.features.misc.BrewingStandOverlay
import at.hannibal2.skyhanni.features.misc.ButtonOnPause
import at.hannibal2.skyhanni.features.misc.CollectionTracker
@@ -520,6 +521,7 @@ class SkyHanniMod {
loadModule(GardenVisitorFeatures())
loadModule(GardenInventoryNumbers())
loadModule(GardenVisitorTimer())
+ loadModule(MinionXp())
loadModule(GardenNextPlotPrice())
loadModule(GardenCropMilestoneDisplay)
loadModule(GardenCustomKeybinds)
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/minion/MinionsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/minion/MinionsConfig.java
index d54e3d464..9fcc10341 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/minion/MinionsConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/minion/MinionsConfig.java
@@ -36,6 +36,12 @@ public class MinionsConfig {
public boolean hopperProfitDisplay = true;
@Expose
+ @ConfigOption(name = "Show Xp", desc = "Shows how many Exp you will get")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean xpDisplay = true;
+
+ @Expose
public Position hopperProfitPos = new Position(360, 90, false, true);
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/MinionXPJson.java b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/MinionXPJson.java
new file mode 100644
index 000000000..44f66b8b8
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/MinionXPJson.java
@@ -0,0 +1,10 @@
+package at.hannibal2.skyhanni.data.jsonobjects.repo;
+
+import com.google.gson.annotations.Expose;
+
+import java.util.Map;
+
+public class MinionXPJson {
+ @Expose
+ public Map<String, Map<String, Double>> minion_xp;
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/events/MinionOpenEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/MinionOpenEvent.kt
index 5d577b6ee..4cbb112de 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/MinionOpenEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/MinionOpenEvent.kt
@@ -1,5 +1,7 @@
package at.hannibal2.skyhanni.events
+import at.hannibal2.skyhanni.utils.LorenzVec
import net.minecraft.item.ItemStack
-class MinionOpenEvent(val inventoryName: String, val inventoryItems: Map<Int, ItemStack>) : LorenzEvent() \ No newline at end of file
+class MinionOpenEvent(val inventoryName: String, val inventoryItems: Map<Int, ItemStack>) : LorenzEvent()
+class MinionStorageOpenEvent(val position: LorenzVec?, val inventoryItems: Map<Int, ItemStack>) : LorenzEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt
index 9eab0fdde..a6101ceb8 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt
@@ -12,6 +12,7 @@ import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent
import at.hannibal2.skyhanni.events.LorenzTickEvent
import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
import at.hannibal2.skyhanni.events.MinionOpenEvent
+import at.hannibal2.skyhanni.events.MinionStorageOpenEvent
import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled
import at.hannibal2.skyhanni.utils.BlockUtils.getBlockStateAt
import at.hannibal2.skyhanni.utils.InventoryUtils
@@ -51,11 +52,9 @@ import java.awt.Color
class MinionFeatures {
private val config get() = SkyHanniMod.feature.minions
private var lastClickedEntity: LorenzVec? = null
- private var lastMinion: LorenzVec? = null
private var newMinion: LorenzVec? = null
private var newMinionName: String? = null
private var lastMinionOpened = 0L
- private var minionInventoryOpen = false
private var lastInventoryClosed = 0L
private var coinsPerDay = ""
@@ -91,6 +90,10 @@ class MinionFeatures {
val entity = minecraft.pointedEntity
if (entity != null) {
lastClickedEntity = entity.getLorenzVec()
+ return
+ }
+ minecraft.thePlayer.rayTrace(16.0, 1.0f)?.let {
+ lastStorage = it.blockPos.toLorenzVec()
}
}
@@ -123,13 +126,17 @@ class MinionFeatures {
fun onInventoryOpen(event: InventoryFullyOpenedEvent) {
if (!LorenzUtils.inSkyBlock) return
if (LorenzUtils.skyBlockIsland != IslandType.PRIVATE_ISLAND) return
- if (!event.inventoryName.contains(" Minion ")) return
+ if (!event.inventoryName.contains("Minion ")) return
event.inventoryItems[48]?.let {
if ("§aCollect All" == it.name) {
MinionOpenEvent(event.inventoryName, event.inventoryItems).postAndCatch()
+ return
}
}
+
+ MinionStorageOpenEvent(lastStorage, event.inventoryItems).postAndCatch()//TODO
+ minionStorageInventoryOpen = true
}
@SubscribeEvent
@@ -159,6 +166,7 @@ class MinionFeatures {
@SubscribeEvent
fun onInventoryClose(event: InventoryCloseEvent) {
+ minionStorageInventoryOpen = false
if (!minionInventoryOpen) return
val minions = minions ?: return
@@ -172,6 +180,7 @@ class MinionFeatures {
if (location !in minions) {
minions[location]!!.lastClicked = 0
}
+ MinionXp.onMinionClose()
}
@SubscribeEvent
@@ -224,6 +233,7 @@ class MinionFeatures {
lastMinion = null
lastMinionOpened = 0L
minionInventoryOpen = false
+ minionStorageInventoryOpen = false
}
@SubscribeEvent
@@ -326,6 +336,12 @@ class MinionFeatures {
}
companion object {
+
+ var lastMinion: LorenzVec? = null
+ var lastStorage: LorenzVec? = null
+ var minionInventoryOpen = false
+ var minionStorageInventoryOpen = false
+
private var minions: Map<LorenzVec, Storage.ProfileSpecific.MinionConfig>?
get() {
return ProfileStorageData.profileSpecific?.minions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/minion/MinionXp.kt b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionXp.kt
new file mode 100644
index 000000000..80dd9d9aa
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionXp.kt
@@ -0,0 +1,194 @@
+package at.hannibal2.skyhanni.features.minion
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.jsonobjects.repo.MinionXPJson
+import at.hannibal2.skyhanni.events.IslandChangeEvent
+import at.hannibal2.skyhanni.events.MinionOpenEvent
+import at.hannibal2.skyhanni.events.MinionStorageOpenEvent
+import at.hannibal2.skyhanni.events.RepositoryReloadEvent
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import net.minecraft.block.BlockChest
+import net.minecraft.client.Minecraft
+import net.minecraft.item.Item
+import net.minecraft.item.ItemStack
+import net.minecraftforge.event.entity.player.ItemTooltipEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.util.EnumMap
+
+class MinionXp {
+
+ private val config get() = SkyHanniMod.feature.minions
+
+ data class XpInfo(val type: XpType, val amount: Double)
+
+ private data class MinionStorage(val position: LorenzVec, val xpList: EnumMap<XpType, Double>) {
+ val timestamp: SimpleTimeMark = SimpleTimeMark.now()
+ }
+
+ private data class PrimitiveItemStack(val name: NEUInternalName, val stackSize: Int)
+
+ private fun toPrimitiveItemStack(itemStack: ItemStack) =
+ PrimitiveItemStack(itemStack.getInternalName(), itemStack.stackSize)
+
+ enum class XpType {
+ Farming,
+ Mining,
+ Combat,
+ Foraging,
+ Fishing,
+ Alchemy
+ }
+
+ private var collectItem: Item? = null
+
+ private val minionStorages = mutableListOf<MinionStorage>()
+
+ @SubscribeEvent
+ fun onMinionOpen(event: MinionOpenEvent) {
+ if (!config.xpDisplay) return
+
+ collectItem = event.inventoryItems[48]?.item
+ collectItemXpList.clear()
+
+ val xpTotal = handleItems(event.inventoryItems, true)
+
+ val missesStorage = MinionFeatures.lastMinion?.let { minionPosition ->
+ getStorageXpAndUpdateTotal(minionPosition, xpTotal)
+ } ?: false
+
+ collectItemXpList.addAll(xpTotal.map { (type, amount) -> collectMessage(type, amount) })
+ if (missesStorage) {
+ collectItemXpList.add("")
+ collectItemXpList.add("§cError: No Minion Storage Data")
+ collectItemXpList.add("§eOpen Storage to get Correct Value")
+ }
+ collectItemXpList.add("")
+ }
+
+ private fun getStorageXpAndUpdateTotal(
+ minionPosition: LorenzVec,
+ xpTotal: EnumMap<XpType, Double>
+ ): Boolean {
+ if (!getHasStorage(minionPosition)) return false
+ val storage = minionStorages.firstOrNull {
+ it.position.distanceSq(minionPosition) <= 2.5 && it.timestamp.passedSince().inWholeMinutes < 20
+ }
+
+ return if (storage != null) {
+ storage.xpList.forEach { (type, amount) ->
+ xpTotal.compute(type) { _, currentAmount -> (currentAmount ?: 0.0) + amount }
+ }
+ false
+ } else {
+ true
+ }
+
+ }
+
+ private fun handleItems(inventoryItems: Map<Int, ItemStack>, isMinion: Boolean): EnumMap<XpType, Double> {
+ val xpTotal = EnumMap<XpType, Double>(XpType::class.java)
+ inventoryItems.filter {
+ it.value.getLore().isNotEmpty() && (!isMinion || it.key in listOf(21..26, 30..35, 39..44).flatten())
+ }.forEach { (_, itemStack) ->
+ val item = toPrimitiveItemStack(itemStack)
+ val name = item.name
+ val xp = xpInfoMap[name] ?: return@forEach
+
+ //TODO add wisdom and Derpy to calculation and random extra Exp Events
+ val xpAmount = xp.amount * item.stackSize
+
+ xpItemMap[item] = collectMessage(xp.type, xpAmount)
+ xpTotal.compute(xp.type) { _, currentAmount -> (currentAmount ?: 0.0) + xpAmount }
+ }
+ return xpTotal
+ }
+
+ @SubscribeEvent
+ fun onMinionStorageOpen(event: MinionStorageOpenEvent) {
+ if (!config.xpDisplay) return
+
+ val xpTotal = handleItems(event.inventoryItems, false)
+
+ if (event.position == null) return
+ minionStorages.removeIf { it.position == event.position }
+ minionStorages.add(MinionStorage(event.position, xpTotal))
+ }
+
+ private fun collectMessage(type: XpType, amount: Double) =
+ "§7Collect to get: §b${amount.addSeparators()} §e${type.name} XP"
+
+ private fun getHasStorage(minionPosition: LorenzVec): Boolean {
+ val positionsToCheck = listOf(
+ LorenzVec(1, 0, 0), LorenzVec(0, 0, 1),
+ LorenzVec(-1, 0, 0), LorenzVec(0, 0, -1)
+ )
+
+ return positionsToCheck.any { position ->
+ val pos = minionPosition.add(position).toBlocPos()
+ val block = Minecraft.getMinecraft().theWorld.getBlockState(pos).block
+ block is BlockChest
+ }
+ }
+
+ @SubscribeEvent
+ fun onItemTooltipEvent(event: ItemTooltipEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.xpDisplay) return
+ when {
+ MinionFeatures.minionInventoryOpen -> {
+ addXpInfoToTooltip(event)
+ if (collectItem == event.itemStack.item) {
+ collectItemXpList.forEachIndexed { i, it ->
+ event.toolTip.add(i + 1, it)
+ }
+ }
+ }
+
+ MinionFeatures.minionStorageInventoryOpen -> {
+ addXpInfoToTooltip(event)
+ }
+ }
+ }
+
+ private fun addXpInfoToTooltip(event: ItemTooltipEvent) {
+ xpItemMap[toPrimitiveItemStack(event.itemStack)]?.let {
+ event.toolTip.add("")
+ event.toolTip.add(it)
+ }
+ }
+
+ @SubscribeEvent
+ fun onIslandChangeEvent(event: IslandChangeEvent) {
+ minionStorages.clear()
+ xpItemMap.clear()
+ collectItemXpList.clear()
+ }
+
+ companion object {
+ private val xpItemMap: MutableMap<PrimitiveItemStack, String> = mutableMapOf()
+ private val collectItemXpList: MutableList<String> = mutableListOf()
+ fun onMinionClose() {
+ xpItemMap.clear()
+ collectItemXpList.clear()
+ }
+ }
+
+ @SubscribeEvent
+ fun onRepoReload(event: RepositoryReloadEvent) {
+ xpInfoMap = event.getConstant<MinionXPJson>("MinionXP").minion_xp.mapNotNull { xpType ->
+ xpType.value.mapNotNull { it.key.asInternalName() to XpInfo(XpType.valueOf(xpType.key), it.value) }
+ }.flatten().toMap()
+ }
+
+ private var xpInfoMap: Map<NEUInternalName, XpInfo> = hashMapOf()
+}
+
+/* it.key.asInternalName() to
+ XpInfo(XpType.valueOf(it.value.type), it.value.value) */