diff options
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 |