aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--FEATURES.md3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/Features.java9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Garden.java50
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Hidden.java6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Misc.java2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt27
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneDisplay.kt168
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt2
9 files changed, 217 insertions, 54 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b93c125b..2c6e19c76 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,7 +17,9 @@
+ Added **Visitor Timer** - Timer when the next visitor will appear, and a number how many visitors are already waiting.
+ Added **Visitor Notification** - Show as title and in chat when a new visitor is visiting your island.
+ Added **Plot Price** - Show the price of the plot in coins when inside the Configure Plots inventory.
-+ Added **Garden Crop Milestone Display**. (Requires an tool with either an counter or cultivating enchantment)
++ Added **Garden Crop Milestone Display** - Shows the progress and ETA until the next crop milestone is reached and the current crops/minute value. (Requires an tool with either an counter or cultivating enchantment) Shows
++ Added **Best Crop Display** - Lists all crops and their ETA till next milestone. Sorts for best crop for getting garden level or skyblock level.
+
### Features from other Mods
> *The following features are only there because I want them when testing SkyHanni features without other mods present.*
diff --git a/FEATURES.md b/FEATURES.md
index a21f6e1cc..5654d9596 100644
--- a/FEATURES.md
+++ b/FEATURES.md
@@ -169,7 +169,8 @@
+ **Visitor Timer** - Timer when the next visitor will appear, and a number how many visitors are already waiting.
+ **Visitor Notification** - Show as title and in chat when a new visitor is visiting your island.
+ **Plot Price** - Show the price of the plot in coins when inside the Configure Plots inventory.
-+ **Garden Crop Milestone Display**. (Requires an tool with either an counter or cultivating enchantment)
++ **Garden Crop Milestone Display** - Shows the progress and ETA until the next crop milestone is reached and the current crops/minute value. (Requires an tool with either an counter or cultivating enchantment) Shows
++ **Best Crop Display** - Lists all crops and their ETA till next milestone. Sorts for best crop for getting garden level or skyblock level.
## Commands
- /wiki (using hypixel-skyblock.fandom.com instead of Hypixel wiki)
diff --git a/src/main/java/at/hannibal2/skyhanni/config/Features.java b/src/main/java/at/hannibal2/skyhanni/config/Features.java
index 61dcf0de7..094d0a043 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/Features.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/Features.java
@@ -152,8 +152,13 @@ public class Features extends Config {
return;
}
- if (runnableId.equals("cropMilestone")) {
- editOverlay(activeConfigCategory, 200, 16, garden.cropMilestoneDisplayPos);
+ if (runnableId.equals("cropMilestoneProgress")) {
+ editOverlay(activeConfigCategory, 200, 16, garden.cropMilestoneProgressDisplayPos);
+ return;
+ }
+
+ if (runnableId.equals("cropMilestoneNext")) {
+ editOverlay(activeConfigCategory, 200, 16, garden.cropMilestoneNextDisplayPos);
return;
}
}
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 6ada96ef0..91331bbd0 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java
@@ -27,7 +27,7 @@ public class Garden {
@ConfigOption(name = "Copper Price Position", desc = "")
@ConfigEditorButton(runnableId = "skyMartCopperPrice", buttonText = "Edit")
@ConfigAccordionId(id = 0)
- public Position skyMartCopperPricePos = new Position(44, -108, false, true);
+ public Position skyMartCopperPricePos = new Position(188, -105, false, true);
@Expose
@ConfigOption(name = "Visitor", desc = "")
@@ -51,7 +51,7 @@ public class Garden {
@ConfigOption(name = "Visitor Timer Position", desc = "")
@ConfigEditorButton(runnableId = "visitorTimer", buttonText = "Edit")
@ConfigAccordionId(id = 2)
- public Position visitorTimerPos = new Position(0, 0, false, true);
+ public Position visitorTimerPos = new Position(-373, -203, false, true);
@Expose
@ConfigOption(name = "Visitor Items Needed", desc = "")
@@ -69,7 +69,7 @@ public class Garden {
@ConfigOption(name = "Items Needed Position", desc = "")
@ConfigEditorButton(runnableId = "visitorNeeds", buttonText = "Edit")
@ConfigAccordionId(id = 3)
- public Position visitorNeedsPos = new Position(0, 0, false, true);
+ public Position visitorNeedsPos = new Position(155, -57, false, true);
@Expose
@ConfigOption(name = "Only when Close", desc = "Only show the needed items when close to the visitors.")
@@ -119,19 +119,55 @@ public class Garden {
@Expose
@ConfigOption(
- name = "Display",
+ name = "Progress Display",
desc = "Show how much more crops are needed to reach the next crop milestone. " +
"§cRequires an tool with either an counter or cultivating enchantment in the hand."
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 5)
- public boolean cropMilestoneDisplay = true;
+ public boolean cropMilestoneProgress = true;
@Expose
@ConfigOption(name = "Display Position", desc = "")
- @ConfigEditorButton(runnableId = "cropMilestone", buttonText = "Edit")
+ @ConfigEditorButton(runnableId = "cropMilestoneProgress", buttonText = "Edit")
@ConfigAccordionId(id = 5)
- public Position cropMilestoneDisplayPos = new Position(0, 0, false, true);
+ public Position cropMilestoneProgressDisplayPos = new Position(-363, 12, false, true);
+
+ @Expose
+ @ConfigOption(name = "Best Crop", desc = "")
+ @ConfigAccordionId(id = 5)
+ @ConfigEditorAccordion(id = 6)
+ public boolean cropMilestoneNext = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Best Display",
+ desc = "Show a display with crops sorted by time.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 6)
+ public boolean cropMilestoneBestDisplay = true;
+
+ @Expose
+ @ConfigOption(name = "Sort Type", desc = "Sort the crops by either garden exp or by skyblock exp.")
+ @ConfigEditorDropdown(values = {"Garden Exp", "SkyBlock Exp"})
+ @ConfigAccordionId(id = 6)
+ public int cropMilestoneBestType = 0;
+
+ @Expose
+ @ConfigOption(name = "Only show top", desc = "Only show the top # crops.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 10,
+ minStep = 1
+ )
+ @ConfigAccordionId(id = 6)
+ public int cropMilestoneShowOnlyBest = 10;
+
+ @Expose
+ @ConfigOption(name = "Display Position", desc = "")
+ @ConfigEditorButton(runnableId = "cropMilestoneNext", buttonText = "Edit")
+ @ConfigAccordionId(id = 6)
+ public Position cropMilestoneNextDisplayPos = new Position(-112, -143, false, true);
@Expose
@ConfigOption(name = "Plot Price", desc = "Show the price of the plot in coins when inside the Configure Plots inventory.")
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Hidden.java b/src/main/java/at/hannibal2/skyhanni/config/features/Hidden.java
index dbe5d61b1..81d2de77b 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/Hidden.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Hidden.java
@@ -32,4 +32,10 @@ public class Hidden {
@Expose
public List<String> crimsonIsleKuudraTiersDone = new ArrayList<>();
+
+ @Expose
+ public Map<String, Long> gardenCropCounter = new HashMap<>();
+
+ @Expose
+ public Map<String, Long> gardenTimeTillNextCropMilestone = new HashMap<>();
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java
index e120bcf04..3b54afd09 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java
@@ -21,7 +21,7 @@ public class Misc {
@ConfigOption(name = "Pet Display Position", desc = "")
@ConfigEditorButton(runnableId = "petDisplay", buttonText = "Edit")
@ConfigAccordionId(id = 0)
- public Position petDisplayPos = new Position(10, 10, false, true);
+ public Position petDisplayPos = new Position(-111, 221, false, true);
@Expose
@ConfigOption(name = "Time", desc = "")
diff --git a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt
index 291b11b81..f38bea5d3 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.data
+import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.CropMilestoneUpdateEvent
import at.hannibal2.skyhanni.events.InventoryOpenEvent
import at.hannibal2.skyhanni.events.ProfileJoinEvent
@@ -29,18 +30,18 @@ class GardenCropMilestones {
@SubscribeEvent
fun onProfileJoin(event: ProfileJoinEvent) {
- cropCounter.clear()
-
- cropCounter["Wheat"] = 0
- cropCounter["Carrot"] = 0
- cropCounter["Potato"] = 0
- cropCounter["Pumpkin"] = 0
- cropCounter["Sugar Cane"] = 0
- cropCounter["Melon"] = 0
- cropCounter["Cactus"] = 0
- cropCounter["Cocoa Beans"] = 0
- cropCounter["Mushroom"] = 0
- cropCounter["Nether Wart"] = 0
+ if (cropCounter.isEmpty()) {
+ cropCounter["Wheat"] = 0
+ cropCounter["Carrot"] = 0
+ cropCounter["Potato"] = 0
+ cropCounter["Pumpkin"] = 0
+ cropCounter["Sugar Cane"] = 0
+ cropCounter["Melon"] = 0
+ cropCounter["Cactus"] = 0
+ cropCounter["Cocoa Beans"] = 0
+ cropCounter["Mushroom"] = 0
+ cropCounter["Nether Wart"] = 0
+ }
}
@SubscribeEvent
@@ -80,7 +81,7 @@ class GardenCropMilestones {
}
companion object {
- val cropCounter = mutableMapOf<String, Long>()
+ val cropCounter: MutableMap<String, Long> get() = SkyHanniMod.feature.hidden.gardenCropCounter
fun getTierForCrops(crops: Long): Int {
var tier = 0
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneDisplay.kt
index 1e224409b..7581a62fb 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneDisplay.kt
@@ -9,8 +9,10 @@ import at.hannibal2.skyhanni.events.OwnInventorItemUpdateEvent
import at.hannibal2.skyhanni.events.ProfileJoinEvent
import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.sorted
import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
+import at.hannibal2.skyhanni.utils.TimeUtils
import net.minecraft.client.Minecraft
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@@ -18,21 +20,28 @@ import net.minecraftforge.fml.common.gameevent.TickEvent
import java.util.*
class GardenCropMilestoneDisplay {
- private val display = mutableListOf<List<Any>>()
+ private val progressDisplay = mutableListOf<List<Any>>()
+ private val bestCropDisplay = mutableListOf<List<Any>>()
private var currentCrop: String? = null
+ private var needsInventory = false
private val cultivatingData = mutableMapOf<String, Int>()
- private var needsInventory = true
+ private val timeTillNextCrop: MutableMap<String, Long> get() = SkyHanniMod.feature.hidden.gardenTimeTillNextCropMilestone
@SubscribeEvent
fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) {
if (!isEnabled()) return
- SkyHanniMod.feature.garden.cropMilestoneDisplayPos.renderStringsAndItems(display)
+ SkyHanniMod.feature.garden.cropMilestoneProgressDisplayPos.renderStringsAndItems(progressDisplay)
+ if (SkyHanniMod.feature.garden.cropMilestoneBestDisplay) {
+ SkyHanniMod.feature.garden.cropMilestoneNextDisplayPos.renderStringsAndItems(bestCropDisplay)
+ }
}
@SubscribeEvent
fun onProfileJoin(event: ProfileJoinEvent) {
- needsInventory = true
+ if (GardenCropMilestones.cropCounter.values.sum() == 0L) {
+ needsInventory = true
+ }
}
@SubscribeEvent
@@ -52,12 +61,46 @@ class GardenCropMilestoneDisplay {
val diff = counter - old
GardenCropMilestones.cropCounter[crop] = GardenCropMilestones.cropCounter[crop]!! + diff
if (currentCrop == crop) {
+ calculateSpeed(diff)
update()
}
}
cultivatingData[crop] = counter
}
+ private var lastSecondStart = 0L
+ private var currentSpeed = 0
+ private var averageSpeedPerSecond = 0
+ private var countInLastSecond = 0
+ private val allCounters = mutableListOf<Int>()
+
+ private fun resetSpeed() {
+ lastSecondStart = 0
+ currentSpeed = 0
+ averageSpeedPerSecond = 0
+ countInLastSecond = 0
+ allCounters.clear()
+ }
+
+ private fun calculateSpeed(diff: Int) {
+ if (System.currentTimeMillis() > lastSecondStart + 1_000) {
+ lastSecondStart = System.currentTimeMillis()
+ if (countInLastSecond > 8) {
+// println("currentSpeed: $currentSpeed")
+ allCounters.add(currentSpeed)
+ while (allCounters.size > 30) {
+ allCounters.removeFirst()
+ }
+// println("allCounters: $allCounters")
+ averageSpeedPerSecond = allCounters.average().toInt()
+ }
+ countInLastSecond = 0
+ currentSpeed = 0
+ }
+ currentSpeed += diff
+ countInLastSecond++
+ }
+
private fun readCounter(itemStack: ItemStack): Int {
if (itemStack.hasTagCompound()) {
val tag = itemStack.tagCompound
@@ -87,52 +130,121 @@ class GardenCropMilestoneDisplay {
val cropInHand = getCropInHand()
if (currentCrop != cropInHand) {
+ resetSpeed()
currentCrop = cropInHand
update()
}
}
private fun update() {
- display.clear()
+ progressDisplay.clear()
+ bestCropDisplay.clear()
currentCrop?.let {
val crops = GardenCropMilestones.cropCounter[it]
if (crops == null) {
println("cropCounter is null for '$it'")
return
}
- display.add(Collections.singletonList("§6Crop Milestones"))
- val list = mutableListOf<Any>()
-
- try {
- val internalName = NEUItems.getInternalName(if (it == "Mushroom") "Red Mushroom" else it)
- val itemStack = NEUItems.getItemStack(internalName)
- list.add(itemStack)
- } catch (e: NullPointerException) {
- e.printStackTrace()
+ drawProgressDisplay(it, crops)
+ if (SkyHanniMod.feature.garden.cropMilestoneBestDisplay) {
+ drawBestDisplay(it)
}
- list.add(it)
- display.add(list)
+ }
+ }
- val currentTier = GardenCropMilestones.getTierForCrops(crops)
+ private fun drawBestDisplay(currentCrop: String) {
+ val gardenExp = SkyHanniMod.feature.garden.cropMilestoneBestType == 0
+ val sorted = if (gardenExp) {
+ val helpMap = mutableMapOf<String, Long>()
+ for ((cropName, time) in timeTillNextCrop) {
+ val crops = GardenCropMilestones.cropCounter[cropName]!!
+ val currentTier = GardenCropMilestones.getTierForCrops(crops)
+ val gardenExpForTier = getGardenExpForTier(currentTier + 1)
+ val fakeTime = time / gardenExpForTier
+ helpMap[cropName] = fakeTime
+ }
+ helpMap.sorted()
+ } else {
+ timeTillNextCrop.sorted()
+ }
- val cropsForCurrentTier = GardenCropMilestones.getCropsForTier(currentTier)
- val nextTier = currentTier + 1
- val cropsForNextTier = GardenCropMilestones.getCropsForTier(nextTier)
+ val title = if (gardenExp) "§2Garden Experience" else "§bSkyBlock Level"
+ bestCropDisplay.add(Collections.singletonList("§eBest Crop Time §7($title§7)"))
- val have = crops - cropsForCurrentTier
- val need = cropsForNextTier - cropsForCurrentTier
+ if (sorted.isEmpty()) {
+ bestCropDisplay.add(Collections.singletonList("§cFarm crops to add them to this list!"))
+ }
- val haveFormat = LorenzUtils.formatInteger(have)
- val needFormat = LorenzUtils.formatInteger(need)
- display.add(Collections.singletonList("§7Progress to Tier $nextTier§8: §e$haveFormat§8/§e$needFormat"))
+ var number = 0
+ for (cropName in sorted.keys) {
+ val millis = timeTillNextCrop[cropName]!!
+ val duration = TimeUtils.formatDuration(millis)
- if (needsInventory) {
- display.add(Collections.singletonList("§cOpen §e/cropmilestones §cto update!"))
+ val isCurrent = currentCrop == cropName
+ val color = if (isCurrent) "§e" else ""
+ number++
+ if (number > SkyHanniMod.feature.garden.cropMilestoneShowOnlyBest && !isCurrent) continue
+ val cropNameDisplay = "$number# $color$cropName"
+ if (gardenExp) {
+ val crops = GardenCropMilestones.cropCounter[cropName]!!
+ val currentTier = GardenCropMilestones.getTierForCrops(crops)
+ val gardenExpForTier = getGardenExpForTier(currentTier + 1)
+ bestCropDisplay.add(Collections.singletonList(" $cropNameDisplay §b$duration §7(§2$gardenExpForTier §7Exp)"))
+ } else {
+ bestCropDisplay.add(Collections.singletonList(" $cropNameDisplay §b$duration"))
}
}
}
+ private fun getGardenExpForTier(gardenLevel: Int) = if (gardenLevel > 30) 300 else gardenLevel * 10
+
+ private fun drawProgressDisplay(it: String, crops: Long) {
+ progressDisplay.add(Collections.singletonList("§6Crop Milestones"))
+
+ val list = mutableListOf<Any>()
+
+ try {
+ val internalName = NEUItems.getInternalName(if (it == "Mushroom") "Red Mushroom" else it)
+ val itemStack = NEUItems.getItemStack(internalName)
+ list.add(itemStack)
+ } catch (e: NullPointerException) {
+ e.printStackTrace()
+ }
+ list.add(it)
+ progressDisplay.add(list)
+
+ val currentTier = GardenCropMilestones.getTierForCrops(crops)
+
+ val cropsForCurrentTier = GardenCropMilestones.getCropsForTier(currentTier)
+ val nextTier = currentTier + 1
+ val cropsForNextTier = GardenCropMilestones.getCropsForTier(nextTier)
+
+ val have = crops - cropsForCurrentTier
+ val need = cropsForNextTier - cropsForCurrentTier
+
+ val haveFormat = LorenzUtils.formatInteger(have)
+ val needFormat = LorenzUtils.formatInteger(need)
+ progressDisplay.add(Collections.singletonList("§7Progress to Tier $nextTier§8:"))
+ progressDisplay.add(Collections.singletonList("§e$haveFormat§8/§e$needFormat"))
+
+ if (averageSpeedPerSecond != 0) {
+ val missing = need - have
+ val missingTimeSeconds = missing / averageSpeedPerSecond
+ val millis = missingTimeSeconds * 1000
+ timeTillNextCrop[it] = millis
+ val duration = TimeUtils.formatDuration(millis)
+ progressDisplay.add(Collections.singletonList("§7In §b$duration"))
+
+ val format = LorenzUtils.formatInteger(averageSpeedPerSecond * 60)
+ progressDisplay.add(Collections.singletonList("§7Crops/minute§8: §e$format"))
+ }
+
+ if (needsInventory) {
+ progressDisplay.add(Collections.singletonList("§cOpen §e/cropmilestones §cto update!"))
+ }
+ }
+
private fun getCropInHand(): String? {
val heldItem = Minecraft.getMinecraft().thePlayer.heldItem ?: return null
if (readCounter(heldItem) == -1) return null
@@ -156,6 +268,6 @@ class GardenCropMilestoneDisplay {
}
private fun isEnabled() = LorenzUtils.inSkyBlock &&
- SkyHanniMod.feature.garden.cropMilestoneDisplay &&
+ SkyHanniMod.feature.garden.cropMilestoneProgress &&
LorenzUtils.skyBlockIsland == IslandType.GARDEN
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt
index 8002c4768..82a8532a1 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt
@@ -13,7 +13,7 @@ object TimeUtils {
showMilliSeconds: Boolean = false,
longName: Boolean = false
): String {
- var milliseconds = millis
+ var milliseconds = millis + 999
val map = mutableMapOf<TimeUnit, Int>()
for (unit in TimeUnit.values()) {
if (unit.ordinal >= biggestUnit.ordinal) {