aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features
diff options
context:
space:
mode:
authornobaboy <84668101+nobaboy@users.noreply.github.com>2024-06-01 12:55:40 +0300
committerGitHub <noreply@github.com>2024-06-01 11:55:40 +0200
commita5af0b8e09d46d445c610d5eaf90b81739652a47 (patch)
tree9fa102ac75aa3fe4828296f3d31441d349ec0e2c /src/main/java/at/hannibal2/skyhanni/features
parent8f7011f956cec5b104c3142ac53e57c4a3798844 (diff)
downloadskyhanni-a5af0b8e09d46d445c610d5eaf90b81739652a47.tar.gz
skyhanni-a5af0b8e09d46d445c610d5eaf90b81739652a47.tar.bz2
skyhanni-a5af0b8e09d46d445c610d5eaf90b81739652a47.zip
Feature: Glacite Mineshafts QOL (#1500)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseLocator.kt124
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoint.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypointType.kt29
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoints.kt96
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpseAPI.kt8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpseType.kt (renamed from src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpeType.kt)2
6 files changed, 264 insertions, 5 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseLocator.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseLocator.kt
new file mode 100644
index 000000000..e1c56ce69
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseLocator.kt
@@ -0,0 +1,124 @@
+package at.hannibal2.skyhanni.features.mining.glacitemineshaft
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.data.PartyAPI
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PartyChatEvent
+import at.hannibal2.skyhanni.data.hypixel.chat.event.PlayerAllChatEvent
+import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
+import at.hannibal2.skyhanni.events.SecondPassedEvent
+import at.hannibal2.skyhanni.utils.ChatUtils
+import at.hannibal2.skyhanni.utils.EntityUtils
+import at.hannibal2.skyhanni.utils.HypixelCommands
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.LocationUtils.canBeSeen
+import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.NumberUtil.formatInt
+import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
+import at.hannibal2.skyhanni.utils.getLorenzVec
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.entity.item.EntityArmorStand
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+// TODO: Maybe implement automatic warp-in for chosen players if the user is not in a party.
+object CorpseLocator {
+ private val config get() = SkyHanniMod.feature.mining.glaciteMineshaft.corpseLocator
+
+ /**
+ * REGEX-TEST: x: -164, y: 8, z: -154 | (Lapis Corpse)
+ * REGEX-TEST: x: 141, y: 14, z: -131
+ * REGEX-TEST: x: -9, y: 135, z: 20 | (Tungsten Corpse)
+ */
+ private val mineshaftCoordsPattern by RepoPattern.pattern(
+ "mineshaft.corpse.coords",
+ "x: (?<x>-?\\d+), y: (?<y>-?\\d+), z: (?<z>-?\\d+)(?:.+)?"
+ )
+
+ private val sharedWaypoints: MutableList<LorenzVec> = mutableListOf()
+
+ private fun findCorpse() {
+ EntityUtils.getAllEntities().filterIsInstance<EntityArmorStand>()
+ .filterNot { corpse -> MineshaftWaypoints.waypoints.any { it.location.distance(corpse.getLorenzVec()) <= 3 } }
+ .filter { entity ->
+ entity.showArms && entity.hasNoBasePlate() && !entity.isInvisible
+ }
+ .forEach { entity ->
+ val helmetName = entity.getCurrentArmor(3).getInternalName()
+ val corpseType = MineshaftWaypointType.getByHelmetOrNull(helmetName) ?: return
+
+ val canSee = entity.getLorenzVec().canBeSeen(-1..3)
+ if (canSee) {
+ ChatUtils.chat("Located a ${corpseType.displayText} and marked its location with a waypoint.")
+ MineshaftWaypoints.waypoints.add(
+ MineshaftWaypoint(
+ waypointType = corpseType,
+ location = entity.getLorenzVec().add(y = 1),
+ isCorpse = true
+ )
+ )
+ }
+ }
+ }
+
+ private fun shareCorpse() {
+ val closestCorpse = MineshaftWaypoints.waypoints.filter { it.isCorpse && !it.shared }
+ .filterNot { corpse ->
+ sharedWaypoints.any { corpse.location.distance(it) <= 5 }
+ }
+ .filter { it.location.distanceToPlayer() <= 5}
+ .minByOrNull { it.location.distanceToPlayer() } ?: return
+
+ val (x, y, z) = closestCorpse.location.toDoubleArray().map { it.toInt() }
+ val type = closestCorpse.waypointType.displayText
+
+ HypixelCommands.partyChat("x: $x, y: $y, z: $z | ($type)")
+ closestCorpse.shared = true
+ }
+
+
+ @SubscribeEvent
+ fun onWorldChange(event: LorenzWorldChangeEvent) {
+ if (sharedWaypoints.isNotEmpty()) sharedWaypoints.clear()
+ }
+
+ @SubscribeEvent
+ fun onSecondPassed(event: SecondPassedEvent) {
+ if (!isEnabled()) return
+
+ findCorpse()
+
+ if (!config.autoSendLocation) return
+ if (MineshaftWaypoints.waypoints.isEmpty()) return
+ if (PartyAPI.partyMembers.isEmpty()) return
+ shareCorpse()
+ }
+
+ @SubscribeEvent
+ fun onPartyChat(event: PartyChatEvent) {
+ handleChatEvent(event.author, event.message)
+ }
+
+ @SubscribeEvent
+ fun onAllChat(event: PlayerAllChatEvent) {
+ handleChatEvent(event.author, event.message)
+ }
+
+ private fun handleChatEvent(author: String, message: String) {
+ if (!isEnabled()) return
+ if (LorenzUtils.getPlayerName() in author) return
+
+ mineshaftCoordsPattern.matchMatcher(message) {
+ val (x, y, z) = listOf(group("x"), group("y"), group("z")).map { it.formatInt() }
+ val location = LorenzVec(x, y, z)
+
+ // Return if someone had already sent a location nearby
+ if (sharedWaypoints.any { it.distance(location) <= 5 }) return
+ sharedWaypoints.add(location)
+ }
+ }
+
+ fun isEnabled() = IslandType.MINESHAFT.isInIsland() && config.enabled
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoint.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoint.kt
new file mode 100644
index 000000000..b45cf9588
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoint.kt
@@ -0,0 +1,10 @@
+package at.hannibal2.skyhanni.features.mining.glacitemineshaft
+
+import at.hannibal2.skyhanni.utils.LorenzVec
+
+data class MineshaftWaypoint(
+ val waypointType: MineshaftWaypointType,
+ val location: LorenzVec,
+ var shared: Boolean = false,
+ var isCorpse: Boolean = false
+)
diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypointType.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypointType.kt
new file mode 100644
index 000000000..31d7a42ce
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypointType.kt
@@ -0,0 +1,29 @@
+package at.hannibal2.skyhanni.features.mining.glacitemineshaft
+
+import at.hannibal2.skyhanni.utils.LorenzColor
+import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
+
+enum class MineshaftWaypointType(
+ val displayText: String,
+ val color: LorenzColor,
+ private val itemName: String? = null
+) {
+ LAPIS("Lapis Corpse", LorenzColor.DARK_BLUE, "LAPIS_ARMOR_HELMET"),
+ UMBER("Umber Corpse", LorenzColor.GOLD, "ARMOR_OF_YOG_HELMET"),
+ TUNGSTEN("Tungsten Corpse", LorenzColor.GRAY, "MINERAL_HELMET"),
+ VANGUARD("Vanguard Corpse", LorenzColor.BLUE, "VANGUARD_HELMET"),
+ ENTRANCE("Entrance", LorenzColor.YELLOW),
+ LADDER("Ladder", LorenzColor.YELLOW)
+ ;
+
+ val helmet by lazy {
+ itemName?.asInternalName()
+ }
+
+ companion object {
+ fun getByHelmetOrNull(internalName: NEUInternalName): MineshaftWaypointType? {
+ return entries.firstOrNull { it.helmet == internalName }
+ }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoints.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoints.kt
new file mode 100644
index 000000000..162ef31ef
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoints.kt
@@ -0,0 +1,96 @@
+package at.hannibal2.skyhanni.features.mining.glacitemineshaft
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.data.PartyAPI
+import at.hannibal2.skyhanni.events.IslandChangeEvent
+import at.hannibal2.skyhanni.events.LorenzKeyPressEvent
+import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent
+import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
+import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled
+import at.hannibal2.skyhanni.utils.HypixelCommands
+import at.hannibal2.skyhanni.utils.LocationUtils
+import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
+import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
+import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import net.minecraft.client.Minecraft
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.milliseconds
+
+// TODO rename to something else to reduce confusion
+object MineshaftWaypoints {
+ private val config get() = SkyHanniMod.feature.mining.glaciteMineshaft
+
+ private const val BLOCKS_FORWARD: Int = 7
+
+ val waypoints: MutableList<MineshaftWaypoint> = mutableListOf()
+ private var timeLastShared = SimpleTimeMark.farPast()
+
+ @SubscribeEvent
+ fun onWorldChange(event: LorenzWorldChangeEvent) {
+ waypoints.clear()
+ }
+
+ @SubscribeEvent
+ fun onIslandChange(event: IslandChangeEvent) {
+ if (event.newIsland != IslandType.MINESHAFT) return
+
+ val playerLocation = LocationUtils.playerLocation().round(0).add(y = -1)
+
+ if (config.mineshaftWaypoints.entranceLocation) {
+ waypoints.add(MineshaftWaypoint(waypointType = MineshaftWaypointType.ENTRANCE, location = playerLocation))
+ }
+
+ if (config.mineshaftWaypoints.ladderLocation) {
+ val vec = Minecraft.getMinecraft().thePlayer.horizontalFacing.directionVec
+ val location = playerLocation
+ // Move 7 blocks in front of the player to be in the ladder shaft
+ .add(x = vec.x * BLOCKS_FORWARD, z = vec.z * BLOCKS_FORWARD)
+ // Adjust 2 blocks to the right to be in the center of the ladder shaft
+ .add(x = vec.z * -2, z = vec.x * 2)
+ // Move 15 blocks down to be at the bottom of the ladder shaft
+ .add(y = -15)
+ waypoints.add(MineshaftWaypoint(waypointType = MineshaftWaypointType.LADDER, location = location))
+ }
+ }
+
+ @SubscribeEvent
+ fun onKeyPress(event: LorenzKeyPressEvent) {
+ if (Minecraft.getMinecraft().currentScreen != null) return
+ if (event.keyCode != config.shareWaypointLocation) return
+ if (timeLastShared.passedSince() < 500.milliseconds) return
+
+ val closestWaypoint = waypoints.filter { it.location.distanceToPlayer() <= 5 }
+ .minByOrNull { it.location.distanceToPlayer() } ?: return
+
+ timeLastShared = SimpleTimeMark.now()
+ val location = closestWaypoint.location
+ val (x, y, z) = location.toDoubleArray().map { it.toInt() }
+ val type = closestWaypoint.waypointType.displayText
+
+ val message = "x: $x, y: $y, z: $z | ($type)"
+
+ if (PartyAPI.partyMembers.isNotEmpty()) {
+ HypixelCommands.partyChat(message)
+ } else {
+ HypixelCommands.allChat(message)
+ }
+ }
+
+ @SubscribeEvent
+ fun onWorldRender(event: LorenzRenderWorldEvent) {
+ if (waypoints.isEmpty()) return
+
+ waypoints
+ .filter {
+ (it.isCorpse && config.corpseLocator.enabled) || (!it.isCorpse && config.mineshaftWaypoints.enabled)
+ }
+ .forEach {
+ event.drawWaypointFilled(it.location, it.waypointType.color.toColor(), seeThroughBlocks = true)
+ event.drawDynamicText(it.location, "§e${it.waypointType.displayText}", 1.0)
+ }
+ }
+
+ fun isEnabled() = IslandType.MINESHAFT.isInIsland() && config.mineshaftWaypoints.enabled
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpseAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpseAPI.kt
index b388a15a8..e8fc4509d 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpseAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpseAPI.kt
@@ -39,7 +39,7 @@ class CorpseAPI {
private var inLoot = false
private val loot = mutableListOf<Pair<String, Int>>()
- private var corpeType: CorpeType? = null
+ private var corpseType: CorpseType? = null
@SubscribeEvent
fun onChat(event: LorenzChatEvent) {
@@ -50,17 +50,17 @@ class CorpseAPI {
startPattern.matchMatcher(message) {
inLoot = true
val name = group("name")
- corpeType = CorpeType.valueOf(name)
+ corpseType = CorpseType.valueOf(name)
return
}
if (!inLoot) return
if (endPattern.matches(message)) {
- corpeType?.let {
+ corpseType?.let {
CorpseLootedEvent(it, loot.toList()).postAndCatch()
}
- corpeType = null
+ corpseType = null
loot.clear()
inLoot = false
return
diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpeType.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpseType.kt
index e2d385de5..7ddfca867 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpeType.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/mining/mineshaft/CorpseType.kt
@@ -2,7 +2,7 @@ package at.hannibal2.skyhanni.features.mining.mineshaft
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
-enum class CorpeType(val displayName: String, private val keyName: String? = null) {
+enum class CorpseType(val displayName: String, private val keyName: String? = null) {
LAPIS("§9Lapis"),
TUNGSTEN("§7Tungsten", "TUNGSTEN_KEY"),
UMBER("§6Umber", "UMBER_KEY"),