diff options
Diffstat (limited to 'src/main/java')
25 files changed, 492 insertions, 317 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 3a8bcede1..dc611609b 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -186,9 +186,11 @@ 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.farming.lane.FarmingLaneAPI +import at.hannibal2.skyhanni.features.garden.farming.lane.FarmingLaneCreator +import at.hannibal2.skyhanni.features.garden.farming.lane.FarmingLaneFeatures import at.hannibal2.skyhanni.features.garden.fortuneguide.CaptureFarmingGear import at.hannibal2.skyhanni.features.garden.inventory.AnitaExtraFarmingFortune import at.hannibal2.skyhanni.features.garden.inventory.GardenCropMilestoneInventory @@ -634,7 +636,9 @@ class SkyHanniMod { loadModule(GardenNextJacobContest) loadModule(WrongFungiCutterWarning()) loadModule(ArmorDropTracker) - loadModule(LaneSwitchNotification()) + loadModule(FarmingLaneAPI) + loadModule(FarmingLaneFeatures) + loadModule(FarmingLaneCreator) loadModule(JoinCrystalHollows()) loadModule(CrystalHollowsNamesInCore()) loadModule(GardenVisitorColorNames) diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt index ee480c6f6..2156872aa 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -40,6 +40,7 @@ import at.hannibal2.skyhanni.features.garden.farming.CropSpeedMeter import at.hannibal2.skyhanni.features.garden.farming.DicerRngDropTracker import at.hannibal2.skyhanni.features.garden.farming.FarmingWeightDisplay import at.hannibal2.skyhanni.features.garden.farming.GardenStartLocation +import at.hannibal2.skyhanni.features.garden.farming.lane.FarmingLaneCreator import at.hannibal2.skyhanni.features.garden.fortuneguide.CaptureFarmingGear import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI import at.hannibal2.skyhanni.features.mining.KingTalismanHelper @@ -293,6 +294,10 @@ object Commands { "shlimbo", "Warps you to Limbo." ) { MiscFeatures().goToLimbo() } + registerCommand( + "shlanedetection", + "Detect a farming lane in garden" + ) { FarmingLaneCreator.commandLaneDetection() } } private fun usersBugFix() { 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 4ed129e77..9fa7e2bcc 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,7 +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.laneswitch.FarmingLaneConfig; 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; @@ -45,9 +45,9 @@ public class GardenConfig { public OptimalSpeedConfig optimalSpeeds = new OptimalSpeedConfig(); @Expose - @ConfigOption(name = "Lane Switching", desc = "") + @ConfigOption(name = "Farming Lane", desc = "") @Accordion - public LaneSwitchConfig laneswitch = new LaneSwitchConfig(); + public FarmingLaneConfig farmingLane = new FarmingLaneConfig(); @Expose @ConfigOption(name = "Garden Level", desc = "") diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/FarmingLaneConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/FarmingLaneConfig.java new file mode 100644 index 000000000..a1ccb9803 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/FarmingLaneConfig.java @@ -0,0 +1,38 @@ +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.ConfigEditorInfoText; +import io.github.moulberry.moulconfig.annotations.ConfigOption; + +public class FarmingLaneConfig { + + @Expose + @ConfigOption(name = "Create Lanes", desc = "In order for those features to work, you first need to create a lane with §e/shlanedetection§7!") + @ConfigEditorInfoText(infoTitle = "Tutorial") + public boolean tutorial = false; + + @Expose + @ConfigOption(name = "Lane Switch Notification", desc = "") + @Accordion + public LaneSwitchNotificationConfig laneSwitchNotification = new LaneSwitchNotificationConfig(); + + @Expose + @ConfigOption(name = "Distance Display", desc = "Shows the remaining distance and time until you reach the end of the current lane.") + @ConfigEditorBoolean + @FeatureToggle + public boolean distanceDisplay = false; + + @Expose + public Position distanceDisplayPosition = new Position(0, 200, false, true); + + @Expose + @ConfigOption(name = "Corner Waypoints", desc = "Show the corner for the current lane in the world.") + @ConfigEditorBoolean + @FeatureToggle + public boolean cornerWaypoints = false; + +} 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 deleted file mode 100644 index 2f83d7fdd..000000000 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -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 index 7989d9b11..48388abbc 100644 --- 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 @@ -1,18 +1,37 @@ package at.hannibal2.skyhanni.config.features.garden.laneswitch; +import at.hannibal2.skyhanni.config.FeatureToggle; 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.ConfigEditorSlider; +import io.github.moulberry.moulconfig.annotations.ConfigEditorText; import io.github.moulberry.moulconfig.annotations.ConfigOption; public class LaneSwitchNotificationConfig { @Expose - @ConfigOption(name = "Sound Settings", desc = "") - @Accordion - public LaneSwitchSoundSettings sound = new LaneSwitchSoundSettings(); + @ConfigOption(name = "Enabled", desc = "Sends a notification when approaching the end of a lane and you should switch lanes.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = false; + + @Expose + @ConfigOption(name = "Seconds Before", desc = "How many seconds before reaching the end of the lane should the warning happen?") + @ConfigEditorSlider( + minValue = 1, + maxValue = 10, + minStep = 1 + ) + public int secondsBefore = 5; @Expose - @ConfigOption(name = "Notification Settings", desc = "") + @ConfigOption(name = "Text", desc = "The text with color to be displayed as the notification.") + @ConfigEditorText + public String text = "&eLane Switch incoming."; + + @Expose + @ConfigOption(name = "Sound Settings", desc = "") @Accordion - public LaneSwitchNotificationSettings settings = new LaneSwitchNotificationSettings(); + public LaneSwitchSoundSettings sound = new LaneSwitchSoundSettings(); } 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 deleted file mode 100644 index b80908f05..000000000 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchNotificationSettings.java +++ /dev/null @@ -1,39 +0,0 @@ -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 index c7214dc5f..dd16d0576 100644 --- 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 @@ -1,6 +1,6 @@ package at.hannibal2.skyhanni.config.features.garden.laneswitch; -import at.hannibal2.skyhanni.features.garden.farming.LaneSwitchNotification; +import at.hannibal2.skyhanni.features.garden.farming.lane.FarmingLaneFeatures; import at.hannibal2.skyhanni.utils.OSUtils; import com.google.gson.annotations.Expose; import io.github.moulberry.moulconfig.annotations.ConfigEditorButton; @@ -12,16 +12,16 @@ public class LaneSwitchSoundSettings { @Expose @ConfigOption(name = "Notification Sound", desc = "The sound played for the notification.") @ConfigEditorText - public String notificationSound = "random.orb"; + public String name = "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; + public float pitch = 1.0f; @ConfigOption(name = "Test Sound", desc = "Test current sound settings.") @ConfigEditorButton(buttonText = "Test") - public Runnable testSound = LaneSwitchNotification::playUserSound; + public Runnable testSound = FarmingLaneFeatures::playUserSound; @ConfigOption(name = "List of Sounds", desc = "A list of available sounds.") @ConfigEditorButton(buttonText = "Open") diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index b69420ab3..912e26ffa 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -18,6 +18,7 @@ import at.hannibal2.skyhanni.features.garden.CropType; import at.hannibal2.skyhanni.features.garden.GardenPlotAPI; import at.hannibal2.skyhanni.features.garden.farming.ArmorDropTracker; import at.hannibal2.skyhanni.features.garden.farming.DicerRngDropTracker; +import at.hannibal2.skyhanni.features.garden.farming.lane.FarmingLane; import at.hannibal2.skyhanni.features.garden.fortuneguide.FarmingItems; import at.hannibal2.skyhanni.features.garden.visitor.VisitorReward; import at.hannibal2.skyhanni.features.mining.powdertracker.PowderTracker; @@ -230,6 +231,9 @@ public class ProfileSpecificStorage { public Map<CropType, LorenzVec> cropStartLocations = new HashMap<>(); @Expose + public Map<CropType, FarmingLane> farmingLanes = new HashMap<>(); + + @Expose public GardenStorage.Fortune fortune = new GardenStorage.Fortune(); public static class Fortune { diff --git a/src/main/java/at/hannibal2/skyhanni/events/CropClickEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/CropClickEvent.kt index 1bc664cda..960724a17 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/CropClickEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/CropClickEvent.kt @@ -2,10 +2,12 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.data.ClickType import at.hannibal2.skyhanni.features.garden.CropType +import at.hannibal2.skyhanni.utils.LorenzVec import net.minecraft.block.state.IBlockState import net.minecraft.item.ItemStack class CropClickEvent( + val position: LorenzVec, val crop: CropType, val blockState: IBlockState, val clickType: ClickType, diff --git a/src/main/java/at/hannibal2/skyhanni/events/farming/FarmingLaneSwitchEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/farming/FarmingLaneSwitchEvent.kt new file mode 100644 index 000000000..3f78fd9c0 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/farming/FarmingLaneSwitchEvent.kt @@ -0,0 +1,6 @@ +package at.hannibal2.skyhanni.events.farming + +import at.hannibal2.skyhanni.events.LorenzEvent +import at.hannibal2.skyhanni.features.garden.farming.lane.FarmingLane + +class FarmingLaneSwitchEvent(val lane: FarmingLane?) : LorenzEvent() 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 76e4cf872..4b27e97f2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt @@ -191,7 +191,7 @@ object GardenAPI { } lastLocation = position - CropClickEvent(cropBroken, blockState, event.clickType, event.itemInHand).postAndCatch() + CropClickEvent(position, cropBroken, blockState, event.clickType, event.itemInHand).postAndCatch() } fun getExpForLevel(requestedLevel: Int): Long { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestStatsSummary.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestStatsSummary.kt index 31f0e3d31..edc1300df 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestStatsSummary.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestStatsSummary.kt @@ -18,7 +18,7 @@ class JacobContestStatsSummary { private var startTime = SimpleTimeMark.farPast() @SubscribeEvent - fun onBlockClick(event: CropClickEvent) { + fun onCropClick(event: CropClickEvent) { if (!isEnabled()) return if (event.clickType != ClickType.LEFT_CLICK) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt index 250725520..bace754b3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt @@ -21,7 +21,7 @@ class CropSpeedMeter { private var snapshot = emptyList<String>() @SubscribeEvent - fun onBlockBreak(event: CropClickEvent) { + fun onCropClick(event: CropClickEvent) { if (!isEnabled()) return if (startCrops.isEmpty()) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt index 7dc92b8d9..47b182ce4 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt @@ -71,7 +71,7 @@ object GardenCropSpeed { } @SubscribeEvent - fun onBlockClick(event: CropClickEvent) { + fun onCropClick(event: CropClickEvent) { if (event.clickType != ClickType.LEFT_CLICK) return lastBrokenCrop = event.crop diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenStartLocation.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenStartLocation.kt index de1730c93..843e8e558 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenStartLocation.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenStartLocation.kt @@ -45,7 +45,7 @@ object GardenStartLocation { } @SubscribeEvent - fun onBlockClick(event: CropClickEvent) { + fun onCropClick(event: CropClickEvent) { if (!isEnabled()) return val startLocations = GardenAPI.storage?.cropStartLocations ?: return val crop = GardenAPI.getCurrentlyFarmedCrop() ?: return 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 deleted file mode 100644 index f83f81bfc..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchNotification.kt +++ /dev/null @@ -1,126 +0,0 @@ -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 (!isEnabled() || !config.distanceUntilSwitch) 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 deleted file mode 100644 index aab0ff4ff..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchUtils.kt +++ /dev/null @@ -1,99 +0,0 @@ -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 { - return if (direction == Direction.WEST_EAST) { - 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 - val isNextNewRow = GardenPlotAPI.plots[plotIndex - 1].box.maxX.absoluteValue.round(0) == 240.0 - val isNextUnlocked = GardenPlotAPI.plots[plotIndex - 1].unlocked - val isNextBarn = GardenPlotAPI.plots[plotIndex - 1].isBarn() - isNextNewRow || !isNextUnlocked || isNextBarn - } else { - if (plotIndex + 1 == 25) return true // check if next plot is out of bounds - val isNextNewRow = (plotIndex + 1) % 5 == 0 - val isNextUnlocked = GardenPlotAPI.plots[plotIndex + 1].unlocked - val isNextBarn = GardenPlotAPI.plots[plotIndex + 1].isBarn() - isNextNewRow || !isNextUnlocked || isNextBarn - } - } else if (direction == Direction.NORTH_SOUTH) { - if (value == Value.TOP) { - if (plotIndex - 1 == -1 || (plotIndex - 5) < 0) return true // check if next plot is out of bounds - val isNextUnlocked = GardenPlotAPI.plots[plotIndex - 5].unlocked - val isNextBarn = GardenPlotAPI.plots[plotIndex - 5].isBarn() - !isNextUnlocked || isNextBarn - } else { - if (plotIndex + 5 > 24) return true // check if next plot is out of bounds - val isNextUnlocked = GardenPlotAPI.plots[plotIndex + 5].unlocked - val isNextBarn = GardenPlotAPI.plots[plotIndex + 5].isBarn() - !isNextUnlocked || isNextBarn - } - } else false - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt index f0a69aa3e..73c8d9a1a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt @@ -30,7 +30,7 @@ class WrongFungiCutterWarning { } @SubscribeEvent - fun onBlockClick(event: CropClickEvent) { + fun onCropClick(event: CropClickEvent) { if (event.clickType != ClickType.LEFT_CLICK) return if (event.crop != CropType.MUSHROOM) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingDirection.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingDirection.kt new file mode 100644 index 000000000..6ce5ebe06 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingDirection.kt @@ -0,0 +1,7 @@ +package at.hannibal2.skyhanni.features.garden.farming.lane + +enum class FarmingDirection { + NORTH_SOUTH, + EAST_WEST, + ; +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLane.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLane.kt new file mode 100644 index 000000000..d4f0071c4 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLane.kt @@ -0,0 +1,9 @@ +package at.hannibal2.skyhanni.features.garden.farming.lane + +import com.google.gson.annotations.Expose + +class FarmingLane( + @Expose val direction: FarmingDirection, + @Expose val min: Double, + @Expose val max: Double, +) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneAPI.kt new file mode 100644 index 000000000..5df0b1358 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneAPI.kt @@ -0,0 +1,69 @@ +package at.hannibal2.skyhanni.features.garden.farming.lane + +import at.hannibal2.skyhanni.events.CropClickEvent +import at.hannibal2.skyhanni.events.GardenToolChangeEvent +import at.hannibal2.skyhanni.events.farming.FarmingLaneSwitchEvent +import at.hannibal2.skyhanni.features.garden.CropType +import at.hannibal2.skyhanni.features.garden.GardenAPI +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds + +object FarmingLaneAPI { + val config get() = GardenAPI.config.farmingLane + + val lanes get() = GardenAPI.storage?.farmingLanes + var currentLane: FarmingLane? = null + private var lastNoLaneWarning = SimpleTimeMark.farPast() + private var lastCrop: CropType? = null + + @SubscribeEvent + fun onGardenToolChange(event: GardenToolChangeEvent) { + handleLaneSwitch(event.crop) + } + + @SubscribeEvent + fun onCropClick(event: CropClickEvent) { + handleLaneSwitch(event.crop) + } + + private fun handleLaneSwitch(crop: CropType?) { + if (crop == lastCrop) return + lastCrop = crop + + val lanes = lanes ?: return + val lane = lanes[crop] + if (lane == null) { + warnNoLane(crop) + } + + if (currentLane == lane) return + currentLane = lane + FarmingLaneSwitchEvent(lane).postAndCatch() + } + + private fun warnNoLane(crop: CropType?) { + if (crop == null || currentLane != null) return + if (!config.distanceDisplay && !config.laneSwitchNotification.enabled) return + + if (lastNoLaneWarning.passedSince() < 30.seconds) return + lastNoLaneWarning = SimpleTimeMark.now() + + ChatUtils.clickableChat( + "No ${crop.cropName} lane defined yet! Use §e/shlanedetection", + command = "shlanedetection" + ) + } + + fun FarmingDirection.getValue(location: LorenzVec): Double = when (this) { + FarmingDirection.NORTH_SOUTH -> location.z + FarmingDirection.EAST_WEST -> location.x + } + + fun FarmingDirection.setValue(location: LorenzVec, value: Double): LorenzVec = when (this) { + FarmingDirection.NORTH_SOUTH -> location.copy(z = value) + FarmingDirection.EAST_WEST -> location.copy(x = value) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneCreator.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneCreator.kt new file mode 100644 index 000000000..b0c5b8d78 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneCreator.kt @@ -0,0 +1,125 @@ +package at.hannibal2.skyhanni.features.garden.farming.lane + +import at.hannibal2.skyhanni.events.CropClickEvent +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.features.garden.CropType +import at.hannibal2.skyhanni.features.garden.GardenAPI +import at.hannibal2.skyhanni.features.garden.farming.lane.FarmingLaneAPI.getValue +import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.LocationUtils +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.math.absoluteValue +import kotlin.math.max +import kotlin.math.min + +object FarmingLaneCreator { + val config get() = FarmingLaneAPI.config + + private var detection = false + private var start: LorenzVec? = null + private var lastLocation: LorenzVec? = null + private var potentialEnd: LorenzVec? = null + private var crop: CropType? = null + private var maxDistance = 0.0 + + fun commandLaneDetection() { + detection = !detection + if (detection) { + ChatUtils.chat("Enabled lane detection. Farm two layers to detect the lane border position.") + } else { + ChatUtils.chat("Stopped lane detection.") + } + } + + @SubscribeEvent + fun onCropClick(event: CropClickEvent) { + if (!isEnabled()) return + + val location = LocationUtils.playerLocation() + + val lastLocation = lastLocation ?: run { + start = location + maxDistance = 0.0 + lastLocation = location + crop = event.crop + return + } + + if (crop != event.crop) { + ChatUtils.chat("Different crop broken, stopping lane detection") + reset() + return + } + if (lastLocation.distance(location) < 1) return + + this.lastLocation = location + val start = start ?: error("start can not be null") + val distance = start.distance(location) + if (distance > maxDistance) { + maxDistance = distance + potentialEnd = null + } else { + val potentialEnd = potentialEnd ?: run { + potentialEnd = location + return + } + if (potentialEnd.distance(location) > 5) { + val crop = crop ?: error("crop can not be null") + saveLane(start, potentialEnd, crop) + } + } + } + + private fun saveLane(a: LorenzVec, b: LorenzVec, crop: CropType) { + val lane = createLane(a, b) + val lanes = FarmingLaneAPI.lanes ?: return + lanes[crop] = lane + FarmingLaneAPI.currentLane = lane + ChatUtils.chat("${crop.cropName} lane saved! Farming Lane features are now working.") + reset() + } + + private fun createLane(a: LorenzVec, b: LorenzVec): FarmingLane { + val diffX = a.x - b.x + val diffZ = a.z - b.z + val direction = + if (diffZ.absoluteValue > diffX.absoluteValue) FarmingDirection.NORTH_SOUTH else FarmingDirection.EAST_WEST + + val min = min(direction.getValue(a), direction.getValue(b)) + val max = max(direction.getValue(a), direction.getValue(b)) + + return FarmingLane(direction, min, max) + } + + private fun reset() { + start = null + lastLocation = null + crop = null + maxDistance = 0.0 + detection = false + } + + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + if (!isEnabled()) return + + start?.let { + event.drawWaypointFilled(it, LorenzColor.WHITE.toColor(), beacon = true) + event.drawDynamicText(it, "start", 1.5) + } + lastLocation?.let { + event.drawWaypointFilled(it, LorenzColor.WHITE.toColor(), beacon = true) + event.drawDynamicText(it, "lastLocation", 1.5) + } + potentialEnd?.let { + event.drawWaypointFilled(it, LorenzColor.WHITE.toColor(), beacon = true) + event.drawDynamicText(it, "potentialEnd", 1.5) + } + } + + private fun isEnabled() = GardenAPI.inGarden() && detection +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneFeatures.kt new file mode 100644 index 000000000..ccaf83b43 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneFeatures.kt @@ -0,0 +1,183 @@ +package at.hannibal2.skyhanni.features.garden.farming.lane + +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.farming.FarmingLaneSwitchEvent +import at.hannibal2.skyhanni.features.garden.GardenAPI +import at.hannibal2.skyhanni.features.garden.farming.lane.FarmingLaneAPI.getValue +import at.hannibal2.skyhanni.features.garden.farming.lane.FarmingLaneAPI.setValue +import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled +import at.hannibal2.skyhanni.utils.LocationUtils +import at.hannibal2.skyhanni.utils.LorenzColor +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.drawDynamicText +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.SoundUtils.playSound +import at.hannibal2.skyhanni.utils.TimeUtils.format +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.math.absoluteValue +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds + +object FarmingLaneFeatures { + val config get() = FarmingLaneAPI.config + + private var currentPositon: Double? = null + private var currentDistance = 0.0 + + private var display = listOf<String>() + private var timeRemaining: Duration? = null + private var lastSpeed = 0.0 + private var validSpeed = false + private var lastTimeFarming = SimpleTimeMark.farPast() + private var lastDirection = 0 + + @SubscribeEvent + fun onFarmingLaneSwitch(event: FarmingLaneSwitchEvent) { + display = emptyList() + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (!GardenAPI.inGarden()) return + if (!event.isMod(2)) return + if (!config.distanceDisplay && !config.laneSwitchNotification.enabled) return + + if (!calculateDistance()) return + if (!GardenAPI.isCurrentlyFarming()) return + + if (calculateSpeed()) { + showWarning() + } + + if (config.distanceDisplay) { + display = buildList { + add("§7Distance until switch: §e${currentDistance.round(1)}") + val color = if (validSpeed) "§b" else "§8" + val timeRemaining = timeRemaining ?: return@buildList + val format = timeRemaining.format(showMilliSeconds = timeRemaining < 20.seconds) + add("§7Time remaining: $color$format") + } + } + } + + private fun calculateDistance(): Boolean { + val lane = FarmingLaneAPI.currentLane ?: return false + val min = lane.min + val max = lane.max + val position = lane.direction.getValue(LocationUtils.playerLocation()) + val outside = position !in min..max + if (outside) { + display = emptyList() + return false + } + + val direction = calculateDirection(position) ?: return false + + currentDistance = when (direction) { + 1 -> (min - position).absoluteValue + -1 -> (max - position).absoluteValue + else -> currentDistance + } + + if (direction != lastDirection) { + // reset farming time, to prevent wrong lane warnings + lastTimeFarming = SimpleTimeMark.farPast() + lastDirection = direction + } + return true + } + + private fun calculateDirection(newPositon: Double): Int? { + val position = currentPositon ?: run { + currentPositon = newPositon + return null + } + currentPositon = newPositon + + val diff = position - newPositon + return if (diff > 0) { + 1 + } else if (diff < 0) { + -1 + } else { + 0 + } + } + + private fun showWarning() { + with(config.laneSwitchNotification) { + if (enabled) { + LorenzUtils.sendTitle(text.replace("&", "§"), 2.seconds) + playUserSound() + } + } + } + + private fun calculateSpeed(): Boolean { + val speedPerSecond = LocationUtils.distanceFromPreviousTick().round(2) + if (speedPerSecond == 0.0) return false + val speedTooSlow = speedPerSecond < 1 + if (speedTooSlow) { + validSpeed = false + return false + } + // only calculate the time if the speed has not changed + if (lastSpeed != speedPerSecond) { + lastSpeed = speedPerSecond + validSpeed = false + return false + } + validSpeed = true + + val timeRemaining = (currentDistance / speedPerSecond).seconds + FarmingLaneFeatures.timeRemaining = timeRemaining + val warnAt = config.laneSwitchNotification.secondsBefore.seconds + if (timeRemaining >= warnAt) { + lastTimeFarming = SimpleTimeMark.now() + return false + } + + // When the player was not inside the farm previously + return lastTimeFarming.passedSince() < warnAt + } + + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + if (!GardenAPI.inGarden()) return + if (!config.cornerWaypoints) return + + val lane = FarmingLaneAPI.currentLane ?: return + val direction = lane.direction + val location = LocationUtils.playerLocation() + val min = direction.setValue(location, lane.min).capAtBuildHeight() + val max = direction.setValue(location, lane.max).capAtBuildHeight() + + event.drawWaypointFilled(min, LorenzColor.YELLOW.toColor(), beacon = true) + event.drawDynamicText(min, "§eLane Corner", 1.5) + event.drawWaypointFilled(max, LorenzColor.YELLOW.toColor(), beacon = true) + event.drawDynamicText(max, "§eLane Corner", 1.5) + } + + private fun LorenzVec.capAtBuildHeight(): LorenzVec = if (y > 76) copy(y = 76.0) else this + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { + if (!GardenAPI.inGarden()) return + if (!config.distanceDisplay) return + + config.distanceDisplayPosition.renderStrings(display, posLabel = "Lane Display") + } + + @JvmStatic + fun playUserSound() { + with(config.laneSwitchNotification.sound) { + SoundUtils.createSound(name, pitch).playSound() + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt index ef1077cf9..0c8abbec0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt @@ -202,7 +202,7 @@ class GardenVisitorTimer { } @SubscribeEvent - fun onBlockBreak(event: CropClickEvent) { + fun onCropClick(event: CropClickEvent) { if (!isEnabled()) return sixthVisitorArrivalTime -= 100.milliseconds |