aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md11
-rw-r--r--OPEN_SOURCE_SOFTWARE.md1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/Features.java4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Diana.java34
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/MinecraftData.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/BurrowDetectEvent.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/BurrowDugEvent.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/ReceiveParticleEvent.kt1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/SoopyGuessBurrowEvent.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowType.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt157
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt224
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt276
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/LorenzVec.kt12
16 files changed, 751 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5566f35b..5e391277d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,12 +2,16 @@
## Version 0.11.1
-### Features
-+ Option to remove the wrong dagger messages from chat.
+### Diana
++ Let Soopy guess the next burrow location for you.
++ Show burrows near you.
++ Show the way from one burrow to another smoothly.
+
+### Crimson Isle
++ Option to remove the wrong blaze slayer dagger messages from chat.
+ Hide particles and fireballs near blaze slayer bosses and demons.
+ Added Option to hide blaze particles.
+ Highlight millenia aged blaze color in red
-+ Hide the vanilla nametag of damage indicator bosses.
### Changes
+ Removed more blaze slayer item drop message spam.
@@ -15,6 +19,7 @@
+ All particles next to ashfang are now hidden when clear ashfang view is enabled.
+ All particles around blaze slayer are hidden when blaze particles is enabled.
+ Hide blocks circling around ashfang.
++ Hide the vanilla nametag of damage indicator bosses.
## Version 0.11
diff --git a/OPEN_SOURCE_SOFTWARE.md b/OPEN_SOURCE_SOFTWARE.md
index fe994fd81..0c6819e85 100644
--- a/OPEN_SOURCE_SOFTWARE.md
+++ b/OPEN_SOURCE_SOFTWARE.md
@@ -11,3 +11,4 @@ SkyHanni would not be possible without the following open source software:
| [Wynntils](https://github.com/Wynntils/Wynntils) | [AGPL 3.0](https://github.com/Wynntils/Wynntils/blob/development/LICENSE) |
| [Skytils](https://github.com/Skytils/SkytilsMod) | [AGPL 3.0](https://github.com/Skytils/SkytilsMod/blob/1.x/LICENSE.md) |
| [Forge1.8.9Template](https://github.com/romangraef/Forge1.8.9Template) | [Unlicensed](https://github.com/romangraef/Forge1.8.9Template/blob/master/LICENSE) |
+| [SoopyV2](https://github.com/Soopyboo32/SoopyV2) | [GPL 3.0](https://github.com/Soopyboo32/SoopyV2/blob/master/LICENSE) |
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
index 7aef3f50b..351fb628e 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
@@ -18,6 +18,9 @@ import at.hannibal2.skyhanni.features.commands.WikiCommand;
import at.hannibal2.skyhanni.features.damageindicator.DamageIndicatorManager;
import at.hannibal2.skyhanni.features.dungeon.*;
import at.hannibal2.skyhanni.features.end.VoidlingExtremistColor;
+import at.hannibal2.skyhanni.features.event.diana.GriffinBurrowHelper;
+import at.hannibal2.skyhanni.features.event.diana.GriffinBurrowParticleFinder;
+import at.hannibal2.skyhanni.features.event.diana.SoopyGuessBurrow;
import at.hannibal2.skyhanni.features.fishing.SeaCreatureManager;
import at.hannibal2.skyhanni.features.fishing.SeaCreatureMessageShortener;
import at.hannibal2.skyhanni.features.fishing.TrophyFishMessages;
@@ -155,6 +158,9 @@ public class SkyHanniMod {
registerEvent(new StatsTuning());
registerEvent(new NonGodPotEffectDisplay());
registerEvent(new HideBlazeParticles());
+ registerEvent(new SoopyGuessBurrow());
+ registerEvent(new GriffinBurrowHelper());
+ registerEvent(new GriffinBurrowParticleFinder());
Commands.INSTANCE.init();
diff --git a/src/main/java/at/hannibal2/skyhanni/config/Features.java b/src/main/java/at/hannibal2/skyhanni/config/Features.java
index f04d6f95b..605606d8a 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/Features.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/Features.java
@@ -164,6 +164,10 @@ public class Features extends Config {
public Slayer slayer = new Slayer();
@Expose
+ @Category(name = "Diana", desc = "Diana's mythological event.")
+ public Diana diana = new Diana();
+
+ @Expose
@Category(name = "Commands", desc = "Enable or disable mod commands")
public CommandsFeatures commands = new CommandsFeatures();
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Diana.java b/src/main/java/at/hannibal2/skyhanni/config/features/Diana.java
new file mode 100644
index 000000000..55ec5d387
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Diana.java
@@ -0,0 +1,34 @@
+package at.hannibal2.skyhanni.config.features;
+
+import at.hannibal2.skyhanni.config.core.config.annotations.ConfigAccordionId;
+import at.hannibal2.skyhanni.config.core.config.annotations.ConfigEditorAccordion;
+import at.hannibal2.skyhanni.config.core.config.annotations.ConfigEditorBoolean;
+import at.hannibal2.skyhanni.config.core.config.annotations.ConfigOption;
+import com.google.gson.annotations.Expose;
+
+public class Diana {
+
+ @Expose
+ @ConfigOption(name = "Griffin Burrows", desc = "")
+ @ConfigEditorAccordion(id = 0)
+ public boolean griffinBurrows = false;
+
+ @Expose
+ @ConfigOption(name = "Soopy Guess", desc = "Uses §eSoopy's Guess Logic §7to find the next burrow. Does not require SoopyV2 or chat triggers to be installed.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean burrowsSoopyGuess = false;
+
+ @Expose
+ @ConfigOption(name = "Nearby Detection", desc = "Show burrows near you.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean burrowsNearbyDetection = false;
+
+ @Expose
+ @ConfigOption(name = "Smooth Transition", desc = "Show the way from one burrow to another smoothly.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean burrowSmoothTransition = false;
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java b/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java
index d33e70b69..7038014b2 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java
@@ -59,7 +59,7 @@ public class Slayer {
public int blazeFirstDagger = 0;
@Expose
- @ConfigOption(name = "Hide Chat", desc = "Remove the wrong dagger messages from chat.")
+ @ConfigOption(name = "Hide Chat", desc = "Remove the wrong blaze slayer dagger messages from chat.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
public boolean blazeHideDaggerWarning = false;
diff --git a/src/main/java/at/hannibal2/skyhanni/data/MinecraftData.kt b/src/main/java/at/hannibal2/skyhanni/data/MinecraftData.kt
index 9658ab2d3..16facaf90 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/MinecraftData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/MinecraftData.kt
@@ -42,7 +42,8 @@ class MinecraftData {
packet.particleCount,
packet.particleSpeed,
LorenzVec(packet.xOffset, packet.yOffset, packet.zOffset),
- packet.particleArgs
+ packet.isLongDistance,
+ packet.particleArgs,
).postAndCatch()
) {
event.isCanceled = true
diff --git a/src/main/java/at/hannibal2/skyhanni/events/BurrowDetectEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/BurrowDetectEvent.kt
new file mode 100644
index 000000000..cca221932
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/BurrowDetectEvent.kt
@@ -0,0 +1,6 @@
+package at.hannibal2.skyhanni.events
+
+import at.hannibal2.skyhanni.features.event.diana.BurrowType
+import at.hannibal2.skyhanni.utils.LorenzVec
+
+class BurrowDetectEvent(val burrowLocation: LorenzVec, val type: BurrowType) : LorenzEvent() \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/events/BurrowDugEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/BurrowDugEvent.kt
new file mode 100644
index 000000000..bd4963c88
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/BurrowDugEvent.kt
@@ -0,0 +1,5 @@
+package at.hannibal2.skyhanni.events
+
+import at.hannibal2.skyhanni.utils.LorenzVec
+
+class BurrowDugEvent(val burrowLocation: LorenzVec): LorenzEvent() \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/events/ReceiveParticleEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/ReceiveParticleEvent.kt
index 81c849d3c..22c15606c 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/ReceiveParticleEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/ReceiveParticleEvent.kt
@@ -11,5 +11,6 @@ class ReceiveParticleEvent(
val count: Int,
val speed: Float,
val offset: LorenzVec,
+ val longDistance: Boolean,
val particleArgs: IntArray
) : LorenzEvent() \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/events/SoopyGuessBurrowEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SoopyGuessBurrowEvent.kt
new file mode 100644
index 000000000..66537284e
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/SoopyGuessBurrowEvent.kt
@@ -0,0 +1,5 @@
+package at.hannibal2.skyhanni.events
+
+import at.hannibal2.skyhanni.utils.LorenzVec
+
+class SoopyGuessBurrowEvent(val guessLocation: LorenzVec): LorenzEvent() \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowType.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowType.kt
new file mode 100644
index 000000000..b7d589440
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowType.kt
@@ -0,0 +1,10 @@
+package at.hannibal2.skyhanni.features.event.diana
+
+import at.hannibal2.skyhanni.utils.LorenzColor
+
+enum class BurrowType(val text: String, val color: LorenzColor) {
+ START("§aStart",LorenzColor.GREEN),
+ MOB("§cMob",LorenzColor.RED),
+ TREASURE("§6Treasure",LorenzColor.GOLD),
+ UNKNOWN("§fUnknown?!",LorenzColor.WHITE),
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt
new file mode 100644
index 000000000..6c284f255
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt
@@ -0,0 +1,157 @@
+package at.hannibal2.skyhanni.features.event.diana
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.BurrowDetectEvent
+import at.hannibal2.skyhanni.events.BurrowDugEvent
+import at.hannibal2.skyhanni.events.SoopyGuessBurrowEvent
+import at.hannibal2.skyhanni.utils.BlockUtils.getBlockAt
+import at.hannibal2.skyhanni.utils.LocationUtils
+import at.hannibal2.skyhanni.utils.LorenzColor
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.RenderUtils.drawColor
+import at.hannibal2.skyhanni.utils.RenderUtils.drawString
+import net.minecraft.init.Blocks
+import net.minecraftforge.client.event.RenderWorldLastEvent
+import net.minecraftforge.event.world.WorldEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class GriffinBurrowHelper {
+
+ private var guessLocation: LorenzVec? = null
+ private var particleBurrows = mutableMapOf<LorenzVec, BurrowType>()
+ private var animationLocation: LorenzVec? = null
+ private var lastDug: LorenzVec? = null
+
+ @SubscribeEvent
+ fun onSoopyGuessBurrow(event: SoopyGuessBurrowEvent) {
+// if (!SkyHanniMod.feature.diana.burrowsSoopyGuess) return
+
+ if (SkyHanniMod.feature.diana.burrowsSoopyGuess) {
+ if (guessLocation == null) {
+ animationLocation = lastDug ?: LocationUtils.playerLocation()
+ }
+ }
+ guessLocation = event.guessLocation
+ if (SkyHanniMod.feature.diana.burrowsNearbyDetection) {
+ checkRemoveGuess(false)
+ }
+ }
+
+ @SubscribeEvent
+ fun onBurrowDetect(event: BurrowDetectEvent) {
+ particleBurrows[event.burrowLocation] = event.type
+
+ if (SkyHanniMod.feature.diana.burrowsNearbyDetection) {
+ checkRemoveGuess(true)
+ }
+ }
+
+ private fun checkRemoveGuess(animation: Boolean) {
+ guessLocation?.let { guessRaw ->
+ val guess = findBlock(guessRaw)
+ if (particleBurrows.any { guess.distance(it.key) < 20 }) {
+ if (animation) {
+ animationLocation = guess
+ }
+ guessLocation = null
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onBurrowDug(event: BurrowDugEvent) {
+ val location = event.burrowLocation
+ particleBurrows.remove(location)
+ if (particleBurrows.isNotEmpty()) {
+ animationLocation = location
+ }
+ lastDug = location
+ }
+
+ @SubscribeEvent
+ fun onWorldChange(event: WorldEvent.Load) {
+ guessLocation = null
+ animationLocation = null
+ lastDug = null
+ particleBurrows.clear()
+ }
+
+ private fun findBlock(point: LorenzVec): LorenzVec {
+ var gY = 131.0
+
+ var searchGrass = true
+ while ((if (searchGrass) LorenzVec(point.x, gY, point.z).getBlockAt() != Blocks.grass else LorenzVec(
+ point.x,
+ gY,
+ point.z
+ ).getBlockAt() == Blocks.air)
+ ) {
+ gY--
+ if (gY < 70) {
+ if (!searchGrass) {
+ break
+ } else {
+ searchGrass = false
+ gY = 131.0
+ }
+ }
+ }
+ return LorenzVec(point.x, gY, point.z)
+ }
+
+ @SubscribeEvent
+ fun onRenderWorld(event: RenderWorldLastEvent) {
+ val playerLocation = LocationUtils.playerLocation()
+ if (SkyHanniMod.feature.diana.burrowsSoopyGuess) {
+ guessLocation?.let {
+ val guessLocation = findBlock(it)
+ val distance = guessLocation.distance(playerLocation)
+ event.drawColor(guessLocation, LorenzColor.WHITE, distance > 10)
+ if (distance < 10) {
+ event.drawString(guessLocation.add(0.5, 1.5, 0.5), "§fSoopy Guess", true)
+ }
+ }
+ }
+
+ if (SkyHanniMod.feature.diana.burrowSmoothTransition) {
+ animationLocation?.let {
+ event.drawColor(it, LorenzColor.WHITE)
+ animationLocation = moveAnimation(it)
+ }
+ }
+
+ if (SkyHanniMod.feature.diana.burrowsNearbyDetection) {
+ for (burrow in particleBurrows) {
+ val location = burrow.key
+ val distance = location.distance(playerLocation)
+ val burrowType = burrow.value
+ event.drawColor(location, burrowType.color, distance > 10)
+ if (distance < 10) {
+ event.drawString(location.add(0.5, 1.5, 0.5), burrowType.text, true)
+ }
+ }
+ }
+ }
+
+ private fun moveAnimation(animation: LorenzVec): LorenzVec? {
+ val list = mutableListOf<LorenzVec>()
+ list.addAll(particleBurrows.keys)
+ guessLocation?.let {
+ val loc = findBlock(it)
+ if (loc.y > 200) {
+ list.add(LorenzVec(loc.x, LocationUtils.playerLocation().y, loc.z))
+ } else {
+ list.add(loc)
+ }
+ }
+ val target = list.minByOrNull { it.distance(animation) } ?: return null
+ val distance = target.distance(animation)
+ if (distance < 0.20) return null
+
+ var vector = target.subtract(animation)
+
+ vector = vector.multiply(1 / vector.length())
+ vector = vector.multiply(0.18)
+ return animation.add(vector)
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt
new file mode 100644
index 000000000..72862c7e2
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt
@@ -0,0 +1,224 @@
+package at.hannibal2.skyhanni.features.event.diana
+
+import at.hannibal2.skyhanni.events.BurrowDetectEvent
+import at.hannibal2.skyhanni.events.BurrowDugEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.PacketEvent
+import at.hannibal2.skyhanni.utils.BlockUtils.getBlockAt
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.toLorenzVec
+import net.minecraft.client.Minecraft
+import net.minecraft.init.Blocks
+import net.minecraft.item.ItemStack
+import net.minecraft.network.play.client.C07PacketPlayerDigging
+import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement
+import net.minecraft.network.play.server.S2APacketParticles
+import net.minecraftforge.event.world.WorldEvent
+import net.minecraftforge.fml.common.eventhandler.EventPriority
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class GriffinBurrowParticleFinder {
+
+ private val recentlyDugParticleBurrows = mutableListOf<LorenzVec>()
+ private val burrows = mutableMapOf<LorenzVec, Burrow>()
+ var lastDugParticleBurrow: LorenzVec? = null
+
+ // private enum class ParticleType(val check: ReceiveParticleEvent.() -> Boolean) {
+// EMPTY({
+// type == net.minecraft.util.EnumParticleTypes.CRIT_MAGIC && count == 4 && speed == 0.01f && offset.x == 0.5 && offset.y == 0.1 && offset.z == 0.5
+// }),
+// MOB({
+// type == net.minecraft.util.EnumParticleTypes.CRIT && count == 3 && speed == 0.01f && offset.x == 0.5 && offset.y == 0.1 && offset.z == 0.5
+//
+// }),
+// TREASURE({
+// type == net.minecraft.util.EnumParticleTypes.DRIP_LAVA && count == 2 && speed == 0.01f && offset.x == 0.35 && offset.y == 0.1 && offset.z == 0.35
+// }),
+// FOOTSTEP({
+// type == net.minecraft.util.EnumParticleTypes.FOOTSTEP && count == 1 && speed == 0.0f && offset.x == 0.05 && offset.y == 0.0 && offset.z == 0.05
+// }),
+// ENCHANT({
+// type == net.minecraft.util.EnumParticleTypes.ENCHANTMENT_TABLE && count == 5 && speed == 0.05f && offset.x == 0.5 && offset.y == 0.4 && offset.z == 0.5
+// });
+//
+// companion object {
+// fun getParticleType(packet: ReceiveParticleEvent): ParticleType? {
+// if (!packet.longDistance) return null
+// for (type in values()) {
+// if (type.check(packet)) {
+// return type
+// }
+// }
+// return null
+// }
+// }
+// }
+//
+// @SubscribeEvent
+// fun onChatPacket(event: ReceiveParticleEvent) {
+// if (!LorenzUtils.inSkyblock) return
+// if (!SkyHanniMod.feature.dev.debugEnabled) return
+//
+// val particleType = getParticleType(event)
+// if (particleType != null) {
+//
+// val location = event.location.toBlocPos().down().toLorenzVec()
+// if (recentlyDugParticleBurrows.contains(location)) return
+// val burrow = particleBurrows.getOrPut(location) { ParticleBurrow(location) }
+//
+// when (particleType) {
+// ParticleType.FOOTSTEP -> burrow.hasFootstep = true
+// ParticleType.ENCHANT -> burrow.hasEnchant = true
+// ParticleType.EMPTY -> burrow.type = 0
+// ParticleType.MOB -> burrow.type = 1
+// ParticleType.TREASURE -> burrow.type = 2
+// }
+//
+// }
+//
+// }
+
+ @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true)
+ fun onChatPacket(event: PacketEvent.ReceiveEvent) {
+ if (!LorenzUtils.inSkyblock) return
+ val packet = event.packet
+
+ if (packet is S2APacketParticles) {
+
+ val particleType = ParticleType.getParticleType(packet)
+ if (particleType != null) {
+
+ val location = packet.toLorenzVec().toBlocPos().down().toLorenzVec()
+ if (recentlyDugParticleBurrows.contains(location)) return
+ val burrow = burrows.getOrPut(location) { Burrow(location) }
+
+ when (particleType) {
+ ParticleType.FOOTSTEP -> burrow.hasFootstep = true
+ ParticleType.ENCHANT -> burrow.hasEnchant = true
+ ParticleType.EMPTY -> burrow.type = 0
+ ParticleType.MOB -> burrow.type = 1
+ ParticleType.TREASURE -> burrow.type = 2
+ }
+
+ if (burrow.hasEnchant && burrow.hasFootstep && burrow.type != -1) {
+ if (!burrow.found) {
+ BurrowDetectEvent(burrow.location, burrow.getType()).postAndCatch()
+ }
+ burrow.found = true
+ }
+ }
+ }
+ }
+
+ private enum class ParticleType(val check: S2APacketParticles.() -> Boolean) {
+ EMPTY({
+ particleType == net.minecraft.util.EnumParticleTypes.CRIT_MAGIC && particleCount == 4 && particleSpeed == 0.01f && xOffset == 0.5f && yOffset == 0.1f && zOffset == 0.5f
+ }),
+ MOB({
+ particleType == net.minecraft.util.EnumParticleTypes.CRIT && particleCount == 3 && particleSpeed == 0.01f && xOffset == 0.5f && yOffset == 0.1f && zOffset == 0.5f
+
+ }),
+ TREASURE({
+ particleType == net.minecraft.util.EnumParticleTypes.DRIP_LAVA && particleCount == 2 && particleSpeed == 0.01f && xOffset == 0.35f && yOffset == 0.1f && zOffset == 0.35f
+ }),
+ FOOTSTEP({
+ particleType == net.minecraft.util.EnumParticleTypes.FOOTSTEP && particleCount == 1 && particleSpeed == 0.0f && xOffset == 0.05f && yOffset == 0.0f && zOffset == 0.05f
+ }),
+ ENCHANT({
+ particleType == net.minecraft.util.EnumParticleTypes.ENCHANTMENT_TABLE && particleCount == 5 && particleSpeed == 0.05f && xOffset == 0.5f && yOffset == 0.4f && zOffset == 0.5f
+ });
+
+ companion object {
+
+ fun getParticleType(packet: S2APacketParticles): ParticleType? {
+ if (!packet.isLongDistance) return null
+ for (type in values()) {
+ if (type.check(packet)) {
+ return type
+ }
+ }
+ return null
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onWorldChange(event: WorldEvent.Load) {
+ burrows.clear()
+ recentlyDugParticleBurrows.clear()
+ }
+
+ @SubscribeEvent
+ fun onChatMessage(event: LorenzChatEvent) {
+ val message = event.message
+ if (message.startsWith("§eYou dug out a Griffin Burrow!") ||
+ message == "§eYou finished the Griffin burrow chain! §r§7(4/4)"
+ ) {
+ val burrow = lastDugParticleBurrow
+ if (burrow != null) {
+ recentlyDugParticleBurrows.add(burrow)
+ lastDugParticleBurrow = null
+ burrows.remove(burrow)?.let {
+ if (it.found) {
+ BurrowDugEvent(it.location).postAndCatch()
+ }
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onSendPacket(event: PacketEvent.SendEvent) {
+ if (!LorenzUtils.inSkyblock) return
+ val packet = event.packet
+ val pos = when {
+ packet is C07PacketPlayerDigging && packet.status == C07PacketPlayerDigging.Action.START_DESTROY_BLOCK -> {
+ packet.position
+ }
+
+ packet is C08PacketPlayerBlockPlacement && packet.stack != null -> packet.position
+ else -> return
+ }.toLorenzVec()
+ if (Minecraft.getMinecraft().thePlayer.heldItem?.isSpade != true || pos.getBlockAt() !== Blocks.grass) return
+ if (burrows.containsKey(pos)) {
+ lastDugParticleBurrow = pos
+ }
+ }
+
+ private val ItemStack.isSpade
+ get() = this.getInternalName() == "ANCESTRAL_SPADE"
+
+ class Burrow(
+ var location: LorenzVec,
+ var hasFootstep: Boolean = false,
+ var hasEnchant: Boolean = false,
+ var type: Int = -1,
+ var found: Boolean = false,
+ ) {
+
+ fun getType(): BurrowType {
+ return when (this.type) {
+ 0 -> BurrowType.START
+ 1 -> BurrowType.MOB
+ 2 -> BurrowType.TREASURE
+ else -> BurrowType.UNKNOWN
+ }
+ }
+
+// private fun getWaypointText(): String {
+// var type = "Burrow"
+// when (this.type) {
+// 0 -> type = "§aStart"
+// 1 -> type = "§cMob"
+// 2 -> type = "§6Treasure"
+// }
+// return "$type §a(Particle)"
+// }
+ }
+}
+
+private fun S2APacketParticles.toLorenzVec(): LorenzVec {
+ return LorenzVec(xCoordinate, yCoordinate, zCoordinate)
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt
new file mode 100644
index 000000000..467cc9f81
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt
@@ -0,0 +1,276 @@
+package at.hannibal2.skyhanni.features.event.diana
+
+import at.hannibal2.skyhanni.events.PlaySoundEvent
+import at.hannibal2.skyhanni.events.ReceiveParticleEvent
+import at.hannibal2.skyhanni.events.SoopyGuessBurrowEvent
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.toLorenzVec
+import net.minecraft.util.EnumParticleTypes
+import net.minecraftforge.event.world.WorldEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.math.*
+
+/**
+ * Taken and ported from Soopyboo32's javascript module SoopyV2
+ */
+class SoopyGuessBurrow {
+
+ var dingIndex = 0
+ var lastDing = 0L
+ var lastDingPitch = 0f
+ var firstPitch = 0f
+ var lastParticlePoint: LorenzVec? = null
+ var lastParticlePoint2: LorenzVec? = null
+ var firstParticlePoint: LorenzVec? = null
+ var particlePoint: LorenzVec? = null
+ var guessPoint: LorenzVec? = null
+
+ var lastSoundPoint: LorenzVec? = null
+ var locs = mutableListOf<LorenzVec>()
+
+ var dingSlope = mutableListOf<Float>()
+
+ var distance: Double? = null
+ var distance2: Double? = null
+
+ @SubscribeEvent
+ fun onWorldChange(event: WorldEvent.Load) {
+ lastDing = 0L
+ lastDingPitch = 0f
+ firstPitch = 0f
+ lastParticlePoint = null
+ lastParticlePoint2 = null
+ lastSoundPoint = null
+ firstParticlePoint = null
+ particlePoint = null
+ guessPoint = null
+ distance = null
+ dingIndex = 0
+ dingSlope.clear()
+ }
+
+ @SubscribeEvent
+ fun onPlaySound(event: PlaySoundEvent) {
+ if (event.soundName != "note.harp") return
+
+ val pitch = event.pitch
+ if (lastDing == 0L) {
+ firstPitch = pitch
+ }
+
+ lastDing = System.currentTimeMillis()
+
+ if (pitch < lastDingPitch) {
+ firstPitch = pitch
+ dingIndex = 0
+ dingSlope.clear()
+ lastDingPitch = pitch
+ lastParticlePoint = null
+ lastParticlePoint2 = null
+ lastSoundPoint = null
+ firstParticlePoint = null
+ distance = null
+ locs.clear()
+ }
+
+ if (lastDingPitch == 0f) {
+ lastDingPitch = pitch
+ distance = null
+ lastParticlePoint = null
+ lastParticlePoint2 = null
+ lastSoundPoint = null
+ firstParticlePoint = null
+ locs.clear()
+ return
+ }
+
+ dingIndex++
+
+ if (dingIndex > 1) dingSlope.add(pitch - lastDingPitch)
+ if (dingSlope.size > 20) dingSlope.removeFirst()
+ val slope = if (dingSlope.isNotEmpty()) dingSlope.reduce { a, b -> a + b }.toDouble() / dingSlope.size else 0.0
+ val pos = event.location
+ lastSoundPoint = pos
+ lastDingPitch = pitch
+
+ if (lastParticlePoint2 == null || particlePoint == null || firstParticlePoint == null) {
+ return
+ }
+
+ distance2 = (Math.E / slope) - firstParticlePoint?.distance(pos)!!
+
+ if (distance2!! > 1000) {
+ distance2 = null
+ guessPoint = null
+ }
+
+ val lineDist = lastParticlePoint2?.distance(particlePoint!!)!!
+
+ distance = distance2!!
+ val changesHelp = particlePoint?.subtract(lastParticlePoint2!!)!!
+ var changes = listOf(changesHelp.x, changesHelp.y, changesHelp.z)
+ changes = changes.map { o -> o / lineDist }
+
+ lastSoundPoint?.let {
+ guessPoint =
+ LorenzVec(
+ it.x + changes[0] * distance!!,
+ it.y + changes[1] * distance!!,
+ it.z + changes[2] * distance!!
+ )
+ }
+ }
+
+ private fun solveEquationThing(x: LorenzVec, y: LorenzVec): LorenzVec {
+ val a =
+ (-y.x * x.y * x.x - y.y * x.y * x.z + y.y * x.y * x.x + x.y * x.z * y.z + x.x * x.z * y.x - x.x * x.z * y.z) / (x.y * y.x - x.y * y.z + x.x * y.z - y.x * x.z + y.y * x.z - y.y * x.x)
+ val b = (y.x - y.y) * (x.x + a) * (x.y + a) / (x.y - x.x)
+ val c = y.x - b / (x.x + a)
+ return LorenzVec(a, b, c)
+ }
+
+ @SubscribeEvent
+ fun onReceiveParticle(event: ReceiveParticleEvent) {
+ val type = event.type
+ if (type != EnumParticleTypes.DRIP_LAVA) return
+ val currLoc = event.location
+
+ var run = false
+ lastSoundPoint?.let {
+ if (abs(currLoc.x - it.x) < 2 && abs(currLoc.y - it.y) < 0.5 && abs(currLoc.z - it.z) < 2) {
+ run = true
+ }
+ }
+ if (run) {
+ if (locs.size < 100 && locs.isEmpty() || locs.last().distance(currLoc) != 0.0) {
+ var distMultiplier = 1.0
+ if (locs.size > 2) {
+ val predictedDist = 0.06507 * locs.size + 0.259
+ val lastPos = locs.last()
+ val actualDist = currLoc.distance(lastPos)
+ distMultiplier = actualDist / predictedDist
+ }
+ locs.add(currLoc)
+
+ if (locs.size > 5 && guessPoint != null) {
+
+ val slopeThing = locs.zipWithNext { a, b ->
+ atan((a.x - b.x) / (a.z - b.z))
+ }
+
+// val slopeThing = mutableListOf<Double>()
+// for ((index, current) in locs.withIndex()) {
+// if (index != 0) {
+// val last = locs[index - 1]
+// slopeThing.add(atan((current.x - last.x) / (current.z - last.z)))
+// }
+// }
+
+ val (a, b, c) = solveEquationThing(
+ LorenzVec(slopeThing.size - 5, slopeThing.size - 3, slopeThing.size - 1), LorenzVec(
+ slopeThing[slopeThing.size - 5],
+ slopeThing[slopeThing.size - 3],
+ slopeThing[slopeThing.size - 1]
+ )
+ )
+
+ val pr1 = mutableListOf<LorenzVec>()
+ val pr2 = mutableListOf<LorenzVec>()
+
+ val start = slopeThing.size - 1
+ val lastPos = locs[start].multiply(1).toDoubleArray()
+ val lastPos2 = locs[start].multiply(1).toDoubleArray()
+
+ var distCovered = 0.0
+
+ val ySpeed = locs[locs.size - 1].x - locs[locs.size - 2].x / hypot(
+ locs[locs.size - 1].x - locs[locs.size - 2].x,
+ locs[locs.size - 1].z - locs[locs.size - 2].x
+ )
+
+ var i = start + 1
+ while (distCovered < distance2!! && i < 10000) {
+ val y = b / (i + a) + c
+ val dist = distMultiplier * (0.06507 * i + 0.259)
+
+ val xOff = dist * sin(y)
+ val zOff = dist * cos(y)
+
+ val dencity = 5
+
+ for (o in 0..dencity) {
+ lastPos[0] += xOff / dencity
+ lastPos[2] += zOff / dencity
+
+ lastPos[1] += ySpeed * dist / dencity
+ lastPos2[1] += ySpeed * dist / dencity
+
+ lastPos2[0] -= xOff / dencity
+ lastPos2[2] -= zOff / dencity
+
+ pr1.add(lastPos.toLorenzVec())
+ pr2.add(lastPos2.toLorenzVec())
+
+
+ lastSoundPoint?.let {
+ distCovered = hypot(lastPos[0] - it.x, lastPos[2] - it.z)
+ }
+
+ if (distCovered > distance2!!) break
+ }
+ i++
+ }
+
+ //Why does this happen?
+ if (pr1.isEmpty()) return
+
+ val p1 = pr1.last()
+ val p2 = pr2.last()
+
+
+ guessPoint?.let {
+ val d1 = ((p1.x - it.x).times(2 + (p1.z - it.z))).pow(2)
+ val d2 = ((p2.x - it.x).times(2 + (p2.z - it.z))).pow(2)
+
+ val finalLocation = if (d1 < d2) {
+ LorenzVec(floor(p1.x), 255.0, floor(p1.z))
+ } else {
+ LorenzVec(floor(p2.x), 255.0, floor(p2.z))
+ }
+ SoopyGuessBurrowEvent(finalLocation).postAndCatch()
+ }
+ }
+ }
+
+ if (lastParticlePoint == null) {
+ firstParticlePoint = currLoc.clone()
+ }
+
+ lastParticlePoint2 = lastParticlePoint
+ lastParticlePoint = particlePoint
+
+ particlePoint = currLoc.clone()
+
+ if (lastParticlePoint2 == null || firstParticlePoint == null || distance2 == null || lastSoundPoint == null) return
+
+
+ val lineDist = lastParticlePoint2?.distance(particlePoint!!)!!
+
+ distance = distance2!!
+
+ val changesHelp = particlePoint?.subtract(lastParticlePoint2!!)!!
+
+ var changes = listOf(changesHelp.x, changesHelp.y, changesHelp.z)
+ changes = changes.map { o -> o / lineDist }
+
+ lastParticlePoint?.let {
+ guessPoint =
+ LorenzVec(
+ it.x + changes[0] * distance!!,
+ it.y + changes[1] * distance!!,
+ it.z + changes[2] * distance!!
+ )
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LorenzVec.kt b/src/main/java/at/hannibal2/skyhanni/utils/LorenzVec.kt
index 0d70b5e5a..6d55a9185 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/LorenzVec.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/LorenzVec.kt
@@ -76,6 +76,12 @@ data class LorenzVec(
fun isZero(): Boolean = x == 0.0 && y == 0.0 && z == 0.0
+ fun clone(): LorenzVec = LorenzVec(x, y, z)
+
+ fun toDoubleArray(): Array<Double> {
+ return arrayOf(x, y, z)
+ }
+
companion object {
fun getFromYawPitch(yaw: Double, pitch: Double): LorenzVec {
val yaw: Double = (yaw + 90) * Math.PI / 180
@@ -109,4 +115,8 @@ fun Entity.getLorenzVec(): LorenzVec = LorenzVec(posX, posY, posZ)
fun Vec3.toLorenzVec(): LorenzVec = LorenzVec(xCoord, yCoord, zCoord)
-fun Rotations.toLorenzVec(): LorenzVec = LorenzVec(x, y, z) \ No newline at end of file
+fun Rotations.toLorenzVec(): LorenzVec = LorenzVec(x, y, z)
+
+fun Array<Double>.toLorenzVec(): LorenzVec {
+ return LorenzVec(this[0], this[1], this[2])
+} \ No newline at end of file