diff options
12 files changed, 374 insertions, 30 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 35e86fbb1..14ba4ce4c 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -181,6 +181,7 @@ import at.hannibal2.skyhanni.features.garden.farming.GardenCropMilestoneDisplay import at.hannibal2.skyhanni.features.garden.farming.GardenCropSpeed import at.hannibal2.skyhanni.features.garden.farming.GardenCustomKeybinds import at.hannibal2.skyhanni.features.garden.farming.GardenStartLocation +import at.hannibal2.skyhanni.features.garden.farming.LaneSwitchNotification import at.hannibal2.skyhanni.features.garden.farming.WildStrawberryDyeNotification import at.hannibal2.skyhanni.features.garden.farming.WrongFungiCutterWarning import at.hannibal2.skyhanni.features.garden.fortuneguide.CaptureFarmingGear @@ -619,6 +620,7 @@ class SkyHanniMod { loadModule(GardenNextJacobContest) loadModule(WrongFungiCutterWarning()) loadModule(ArmorDropTracker) + loadModule(LaneSwitchNotification()) loadModule(JoinCrystalHollows()) loadModule(CrystalHollowsNamesInCore()) loadModule(GardenVisitorColorNames) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/GardenConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/GardenConfig.java index 9ef1fd31b..cd1abbc14 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/GardenConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/GardenConfig.java @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.config.core.config.Position; import at.hannibal2.skyhanni.config.features.garden.composter.ComposterConfig; import at.hannibal2.skyhanni.config.features.garden.cropmilestones.CropMilestonesConfig; +import at.hannibal2.skyhanni.config.features.garden.laneswitch.LaneSwitchConfig; import at.hannibal2.skyhanni.config.features.garden.optimalspeed.OptimalSpeedConfig; import at.hannibal2.skyhanni.config.features.garden.pests.PestsConfig; import at.hannibal2.skyhanni.config.features.garden.visitor.VisitorConfig; @@ -15,7 +16,6 @@ import io.github.moulberry.moulconfig.annotations.ConfigEditorSlider; import io.github.moulberry.moulconfig.annotations.ConfigOption; public class GardenConfig { - @Expose @ConfigOption(name = "SkyMart", desc = "") @Accordion @@ -45,6 +45,11 @@ public class GardenConfig { public OptimalSpeedConfig optimalSpeeds = new OptimalSpeedConfig(); @Expose + @ConfigOption(name = "Lane Switching", desc = "") + @Accordion + public LaneSwitchConfig laneswitch = new LaneSwitchConfig(); + + @Expose @ConfigOption(name = "Garden Level", desc = "") @Accordion public GardenLevelConfig gardenLevels = new GardenLevelConfig(); diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchConfig.java new file mode 100644 index 000000000..2f83d7fdd --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchConfig.java @@ -0,0 +1,32 @@ +package at.hannibal2.skyhanni.config.features.garden.laneswitch; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import com.google.gson.annotations.Expose; +import io.github.moulberry.moulconfig.annotations.Accordion; +import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean; +import io.github.moulberry.moulconfig.annotations.ConfigOption; + +public class LaneSwitchConfig { + + @Expose + @ConfigOption(name = "Enabled", desc = "Sends a notification when approaching the end of a lane.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = false; + + @Expose + @ConfigOption(name = "Distance until Switch", desc = "Displays the remaining distance until the next switch.") + @ConfigEditorBoolean + @FeatureToggle + public boolean distanceUntilSwitch = false; + + @Expose + public Position distanceUntilSwitchPos = new Position(0, 200, false, true); + + @Expose + @ConfigOption(name = "Notifications", desc = "") + @Accordion + public LaneSwitchNotificationConfig notification = new LaneSwitchNotificationConfig(); + +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchNotificationConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchNotificationConfig.java new file mode 100644 index 000000000..7989d9b11 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchNotificationConfig.java @@ -0,0 +1,18 @@ +package at.hannibal2.skyhanni.config.features.garden.laneswitch; + +import com.google.gson.annotations.Expose; +import io.github.moulberry.moulconfig.annotations.Accordion; +import io.github.moulberry.moulconfig.annotations.ConfigOption; + +public class LaneSwitchNotificationConfig { + + @Expose + @ConfigOption(name = "Sound Settings", desc = "") + @Accordion + public LaneSwitchSoundSettings sound = new LaneSwitchSoundSettings(); + + @Expose + @ConfigOption(name = "Notification Settings", desc = "") + @Accordion + public LaneSwitchNotificationSettings settings = new LaneSwitchNotificationSettings(); +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchNotificationSettings.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchNotificationSettings.java new file mode 100644 index 000000000..b80908f05 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchNotificationSettings.java @@ -0,0 +1,39 @@ +package at.hannibal2.skyhanni.config.features.garden.laneswitch; + +import at.hannibal2.skyhanni.utils.LorenzColor; +import com.google.gson.annotations.Expose; +import io.github.moulberry.moulconfig.annotations.ConfigEditorDropdown; +import io.github.moulberry.moulconfig.annotations.ConfigEditorSlider; +import io.github.moulberry.moulconfig.annotations.ConfigEditorText; +import io.github.moulberry.moulconfig.annotations.ConfigOption; + +public class LaneSwitchNotificationSettings { + + @Expose + @ConfigOption(name = "Notification Text", desc = "The text to be displayed as the notification.") + @ConfigEditorText + public String text = "Lane Switch incoming."; + + @ConfigOption(name = "Text Color", desc = "Notification text color. §eIf Chroma is gray, enable Chroma in Chroma settings.") + @Expose + @ConfigEditorDropdown + public LorenzColor color = LorenzColor.YELLOW; + + @Expose + @ConfigOption(name = "Duration", desc = "The time the notification is displayed.") + @ConfigEditorSlider( + minValue = 1F, + maxValue = 10F, + minStep = 0.5F + ) + public double duration = 2.5; + + @Expose + @ConfigOption(name = "Threshold", desc = "How early the notification will be displayed (Seconds before the Lane Switching notification).") + @ConfigEditorSlider( + minValue = 1, + maxValue = 10, + minStep = 1 + ) + public int threshold = 5; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchSoundSettings.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchSoundSettings.java new file mode 100644 index 000000000..c7214dc5f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchSoundSettings.java @@ -0,0 +1,29 @@ +package at.hannibal2.skyhanni.config.features.garden.laneswitch; + +import at.hannibal2.skyhanni.features.garden.farming.LaneSwitchNotification; +import at.hannibal2.skyhanni.utils.OSUtils; +import com.google.gson.annotations.Expose; +import io.github.moulberry.moulconfig.annotations.ConfigEditorButton; +import io.github.moulberry.moulconfig.annotations.ConfigEditorSlider; +import io.github.moulberry.moulconfig.annotations.ConfigEditorText; +import io.github.moulberry.moulconfig.annotations.ConfigOption; + +public class LaneSwitchSoundSettings { + @Expose + @ConfigOption(name = "Notification Sound", desc = "The sound played for the notification.") + @ConfigEditorText + public String notificationSound = "random.orb"; + + @Expose + @ConfigOption(name = "Pitch", desc = "The pitch of the notification sound.") + @ConfigEditorSlider(minValue = 0.5f, maxValue = 2.0f, minStep = 0.1f) + public float notificationPitch = 1.0f; + + @ConfigOption(name = "Test Sound", desc = "Test current sound settings.") + @ConfigEditorButton(buttonText = "Test") + public Runnable testSound = LaneSwitchNotification::playUserSound; + + @ConfigOption(name = "List of Sounds", desc = "A list of available sounds.") + @ConfigEditorButton(buttonText = "Open") + public Runnable listOfSounds = () -> OSUtils.openBrowser("https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/mapping-and-modding-tutorials/2213619-1-8-all-playsound-sound-arguments"); +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt index cf9fbea6f..76e4cf872 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt @@ -143,6 +143,8 @@ object GardenAPI { fun inGarden() = IslandType.GARDEN.isInIsland() + fun isCurrentlyFarming() = inGarden() && GardenCropSpeed.averageBlocksPerSecond > 0.0 + fun ItemStack.getCropType(): CropType? { val internalName = getInternalName() return CropType.entries.firstOrNull { internalName.startsWith(it.toolName) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt index b6825bf43..cac76452e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt @@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.features.garden.pests.SprayType import at.hannibal2.skyhanni.features.misc.LockMouseLook import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.LocationUtils.isPlayerInside import at.hannibal2.skyhanni.utils.LorenzVec @@ -39,7 +40,7 @@ object GardenPlotAPI { return plots.firstOrNull { it.isPlayerInside() } } - class Plot(val id: Int, var inventorySlot: Int, val box: AxisAlignedBB, val middle: LorenzVec) + class Plot(val id: Int, var unlocked: Boolean, var inventorySlot: Int, val box: AxisAlignedBB, val middle: LorenzVec) class PlotData( @Expose @@ -133,7 +134,7 @@ object GardenPlotAPI { val b = LorenzVec(maxX, 256.0, maxY) val middle = a.interpolate(b, 0.5).copy(y = 10.0) val box = a.axisAlignedTo(b).expand(0.0001, 0.0, 0.0001) - list.add(Plot(id, slot, box, middle)) + list.add(Plot(id, false, slot, box, middle)) slot++ } slot += 4 @@ -162,8 +163,9 @@ object GardenPlotAPI { if (event.inventoryName != "Configure Plots") return for (plot in plots) { - val itemName = event.inventoryItems[plot.inventorySlot]?.name ?: continue - plotNamePattern.matchMatcher(itemName) { + val itemStack = event.inventoryItems[plot.inventorySlot] ?: continue + plot.unlocked = itemStack.getLore().all { !it.contains("§7Cost:") } + plotNamePattern.matchMatcher(itemStack.name) { plot.name = group("name") } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchNotification.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchNotification.kt new file mode 100644 index 000000000..ed1c5f074 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchNotification.kt @@ -0,0 +1,126 @@ +package at.hannibal2.skyhanni.features.garden.farming + +import at.hannibal2.skyhanni.config.features.garden.laneswitch.LaneSwitchNotificationSettings +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.features.garden.GardenAPI +import at.hannibal2.skyhanni.features.garden.GardenPlotAPI +import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.plots +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.LocationUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.round +import at.hannibal2.skyhanni.utils.LorenzUtils.sendTitle +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.RenderUtils.renderString +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.SoundUtils.playSound +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.math.absoluteValue +import kotlin.time.Duration.Companion.seconds + +class LaneSwitchNotification { + + private val config get() = GardenAPI.config.laneswitch + + private var bps = 0.0 // Blocks per Second + private var distancesUntilSwitch: List<Double> = listOf() + private var lastBps = 0.0 // Last blocks per Second + private var lastPosition = LorenzVec(0, 0, 0) + private var lastLaneSwitch = SimpleTimeMark.farPast() + private var lastWarning = SimpleTimeMark.farPast() + private var lastDistancesUntilSwitch: List<Double> = listOf() + private var lastDistance = 0.0 + + companion object { + private val config get() = GardenAPI.config.laneswitch + + @JvmStatic + fun playUserSound() { + SoundUtils.createSound( + config.notification.sound.notificationSound, + config.notification.sound.notificationPitch, + ).playSound() + } + } + + private fun switchPossibleInTime(from: LorenzVec, to: LorenzVec, speed: Double, time: Int): Boolean { + return from.distance(to) <= speed * time + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (!isEnabled()) return + val settings = config.notification.settings + val plot = GardenPlotAPI.getCurrentPlot() ?: return + if (!plot.unlocked) return + + val plotIndex = plots.indexOf(plot) + val positon = LocationUtils.playerLocation() + val farmEnd = LaneSwitchUtils.getFarmBounds(plotIndex, positon, lastPosition) ?: return + lastPosition = positon + bps = LocationUtils.distanceFromPreviousTick() + distancesUntilSwitch = farmEnd.map { end -> end.distance(positon).round(2) } + + testForLaneSwitch(settings, farmEnd, positon) + lastBps = bps + } + + private fun testForLaneSwitch( + settings: LaneSwitchNotificationSettings, + farmEnd: List<LorenzVec>, + positon: LorenzVec, + ) { + val farmLength = farmEnd[0].distance(farmEnd[1]) + // farmLength / bps to get the time needed to travel the distance, - the threshold times the farm length divided by the length of 2 plots (to give some room) + val threshold = settings.threshold + // TODO find a name for this variable + val FIND_A_NAME_FOR_ME = threshold * (farmLength / 192) + val farmTraverseTime = ((farmLength / bps) - FIND_A_NAME_FOR_ME).seconds + val bpsDifference = (bps - lastBps).absoluteValue + + if (farmEnd.isEmpty() || lastLaneSwitch.passedSince() < farmTraverseTime || bpsDifference > 20) return + if (!farmEnd.any { switchPossibleInTime(positon, it, bps, threshold) }) return + + with(settings) { + sendTitle(color.getChatColor() + text, duration.seconds) + } + playUserSound() + lastLaneSwitch = SimpleTimeMark.now() + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { + if (!config.distanceUntilSwitch || !isEnabled()) return + if (distancesUntilSwitch.isEmpty()) return + if (lastDistancesUntilSwitch.isEmpty()) { + lastDistancesUntilSwitch = distancesUntilSwitch + } + + val distances = listOf( + distancesUntilSwitch[0] - lastDistancesUntilSwitch[0], + distancesUntilSwitch[1] - lastDistancesUntilSwitch[1] + ) //Get changes in the distances + val distance = if (distances.all { it != 0.0 }) { + if (distances[0] > 0) distancesUntilSwitch[1] else distancesUntilSwitch[0] // get the direction the player is traveling and get the distance to display from that + } else { + lastDistance // display last value if no change is detected + } + + config.distanceUntilSwitchPos.renderString("Distance until Switch: $distance", posLabel = "Movement Speed") + lastDistancesUntilSwitch = distancesUntilSwitch + lastDistance = distance + } + + private fun plotsLoaded(): Boolean { + if (plots.any { it.unlocked }) return true + + if (lastWarning.passedSince() >= 30.seconds) { + ChatUtils.clickableChat("§eOpen your configure plots for lane switch detection to work.", "/desk") + lastWarning = SimpleTimeMark.now() + } + return false + } + + private fun isEnabled() = GardenAPI.isCurrentlyFarming() && config.enabled && plotsLoaded() +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchUtils.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchUtils.kt new file mode 100644 index 000000000..1bdff35de --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchUtils.kt @@ -0,0 +1,104 @@ +package at.hannibal2.skyhanni.features.garden.farming + +import at.hannibal2.skyhanni.features.garden.GardenPlotAPI +import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.isBarn +import at.hannibal2.skyhanni.utils.LorenzUtils.round +import at.hannibal2.skyhanni.utils.LorenzVec +import kotlin.math.absoluteValue + +object LaneSwitchUtils { + + enum class Direction { + WEST_EAST, + NORTH_SOUTH, + ; + } + + enum class Value { + MIN, + MAX, + TOP, + BOTTOM, + ; + } + + fun getFarmBounds(plotIndex: Int, current: LorenzVec, last: LorenzVec): List<LorenzVec>? { + if (GardenPlotAPI.plots[plotIndex].isBarn() || plotIndex == 12) return null + val xVelocity = current.x - last.x + val zVelocity = current.z - last.z + return if (xVelocity.absoluteValue > zVelocity.absoluteValue) { + var xValueMin = 0.0 + var xValueMax = 0.0 + + for (i in 0..4) { + if (isBoundaryPlot(plotIndex - i, Direction.WEST_EAST, Value.MIN)) { + xValueMin = GardenPlotAPI.plots[plotIndex - i].box.minX; break + } + } + for (i in 0..4) { + if (isBoundaryPlot(plotIndex + i, Direction.WEST_EAST, Value.MAX)) { + xValueMax = GardenPlotAPI.plots[plotIndex + i].box.maxX; break + } + } + + val a = LorenzVec(xValueMin, current.y, current.z) + val b = LorenzVec(xValueMax, current.y, current.z) + listOf(a, b) + } else if (xVelocity.absoluteValue < zVelocity.absoluteValue) { + // i * 5 because going vertically is always 5 plots before or after the current + var zValueTop = 0.0 + var zValueBottom = 0.0 + + for (i in 0..4) { + if (isBoundaryPlot(plotIndex - (i * 5), Direction.NORTH_SOUTH, Value.TOP)) { + zValueTop = GardenPlotAPI.plots[plotIndex - (i * 5)].box.minZ; break + } + } + for (i in 0..4) { + if (isBoundaryPlot(plotIndex + (i * 5), Direction.NORTH_SOUTH, Value.BOTTOM)) { + zValueBottom = GardenPlotAPI.plots[plotIndex + (i * 5)].box.maxZ; break + } + } + + val a = LorenzVec(current.x, current.y, zValueTop) + val b = LorenzVec(current.x, current.y, zValueBottom) + listOf(a, b) + } else null + } + + private fun isBoundaryPlot(plotIndex: Int, direction: Direction, value: Value): Boolean { + if (direction == Direction.WEST_EAST) { + val isNextNewRow: Boolean + val isNextUnlocked: Boolean + val isNextBarn: Boolean + if (value == Value.MIN) { + if (plotIndex - 1 == -1) return true // check if next plot is out of bounds + //Check if the next plot's border is 240 and therefore in the previous row + isNextNewRow = GardenPlotAPI.plots[plotIndex - 1].box.maxX.absoluteValue.round(0) == 240.0 + isNextUnlocked = GardenPlotAPI.plots[plotIndex - 1].unlocked + isNextBarn = GardenPlotAPI.plots[plotIndex - 1].isBarn() + } else { + if (plotIndex + 1 == 25) return true // check if next plot is out of bounds + isNextNewRow = (plotIndex + 1) % 5 == 0 + isNextUnlocked = GardenPlotAPI.plots[plotIndex + 1].unlocked + isNextBarn = GardenPlotAPI.plots[plotIndex + 1].isBarn() + } + return isNextNewRow || !isNextUnlocked || isNextBarn + } else if (direction == Direction.NORTH_SOUTH) { + val isNextUnlocked: Boolean + val isNextBarn: Boolean + + if (value == Value.MAX) { + if (plotIndex - 1 == -1 || (plotIndex - 5) < 0) return true // check if next plot is out of bounds + isNextUnlocked = GardenPlotAPI.plots[plotIndex - 5].unlocked + isNextBarn = GardenPlotAPI.plots[plotIndex - 5].isBarn() + } else { + if (plotIndex + 5 > 24) return true // check if next plot is out of bounds + isNextUnlocked = GardenPlotAPI.plots[plotIndex + 5].unlocked + isNextBarn = GardenPlotAPI.plots[plotIndex + 5].isBarn() + } + return !isNextUnlocked || isNextBarn + } + return false + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/MovementSpeedDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/MovementSpeedDisplay.kt index 0af985c67..a30635fb5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/MovementSpeedDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/MovementSpeedDisplay.kt @@ -3,43 +3,20 @@ package at.hannibal2.skyhanni.features.misc import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.enums.OutsideSbFeature import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.utils.LocationUtils import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzUtils.round -import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RenderUtils.renderString -import net.minecraft.client.Minecraft import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.concurrent.fixedRateTimer class MovementSpeedDisplay { private val config get() = SkyHanniMod.feature.misc - private var display = "" - - init { - fixedRateTimer(name = "skyhanni-movement-speed-display", period = 250, initialDelay = 1_000) { - checkSpeed() - } - } - - private fun checkSpeed() { - if (!isEnabled()) return - - val distance = with(Minecraft.getMinecraft().thePlayer) { - val oldPos = LorenzVec(prevPosX, prevPosY, prevPosZ) - val newPos = LorenzVec(posX, posY, posZ) - - // Distance from previous tick, multiplied by TPS - oldPos.distance(newPos) * 20 - } - display = "Movement Speed: ${distance.round(2)}" - } @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { if (!isEnabled()) return - config.playerMovementSpeedPos.renderString(display, posLabel = "Movement Speed") + config.playerMovementSpeedPos.renderString("Movement Speed: ${LocationUtils.distanceFromPreviousTick()}", posLabel = "Movement Speed") } fun isEnabled() = LorenzUtils.onHypixel && diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LocationUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/LocationUtils.kt index 29cc1d569..24b84dd7f 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/LocationUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/LocationUtils.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.utils +import at.hannibal2.skyhanni.utils.LorenzUtils.round import net.minecraft.client.Minecraft import net.minecraft.entity.Entity import net.minecraft.util.AxisAlignedBB @@ -11,6 +12,13 @@ object LocationUtils { fun playerLocation() = Minecraft.getMinecraft().thePlayer.getLorenzVec() + fun distanceFromPreviousTick(): Double = with(Minecraft.getMinecraft().thePlayer) { + val oldPos = LorenzVec(prevPosX, prevPosY, prevPosZ) + val newPos = LorenzVec(posX, posY, posZ) + + (oldPos.distance(newPos) * 20).round(2) + } + fun LorenzVec.distanceToPlayer() = distance(playerLocation()) fun LorenzVec.distanceToPlayerIgnoreY() = distanceIgnoreY(playerLocation()) |