aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal002@users.noreply.github.com>2024-03-19 10:38:45 +0100
committerGitHub <noreply@github.com>2024-03-19 10:38:45 +0100
commita4946da8409040003d96c7d8d43ed394597bf675 (patch)
tree84a189b5f7f20e1e46f82c75c8b0302386085731 /src/main/java/at/hannibal2/skyhanni
parente84c5a0fa9785a65a6edb5340bba19ef96707e1b (diff)
downloadskyhanni-a4946da8409040003d96c7d8d43ed394597bf675.tar.gz
skyhanni-a4946da8409040003d96c7d8d43ed394597bf675.tar.bz2
skyhanni-a4946da8409040003d96c7d8d43ed394597bf675.zip
Improvement: Lane Switch v2 (#1208)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/garden/GardenConfig.java6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/FarmingLaneConfig.java38
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchConfig.java32
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchNotificationConfig.java29
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchNotificationSettings.java39
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/LaneSwitchSoundSettings.java8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/CropClickEvent.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/farming/FarmingLaneSwitchEvent.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestStatsSummary.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenStartLocation.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchNotification.kt126
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/LaneSwitchUtils.kt99
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingDirection.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLane.kt9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneAPI.kt69
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneCreator.kt125
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneFeatures.kt183
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt2
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