diff options
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) */ |