aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal002@users.noreply.github.com>2023-09-02 09:18:48 +0200
committerGitHub <noreply@github.com>2023-09-02 09:18:48 +0200
commitd725572d7a3a41d0c7a588f16f6c9b6bf6aa9ad8 (patch)
treec73336a306271cf859da5b0fa6584c0868006eeb /src/main/java/at/hannibal2/skyhanni/features
parent8338eebd6d73e3034c3d7e96fb0beb2f2ad1476a (diff)
downloadskyhanni-d725572d7a3a41d0c7a588f16f6c9b6bf6aa9ad8.tar.gz
skyhanni-d725572d7a3a41d0c7a588f16f6c9b6bf6aa9ad8.tar.bz2
skyhanni-d725572d7a3a41d0c7a588f16f6c9b6bf6aa9ad8.zip
Following Line (#428)
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/cosmetics/CosmeticFollowingLine.kt129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt b/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt
new file mode 100644
index 000000000..1f84e9e7b
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt
@@ -0,0 +1,129 @@
+package at.hannibal2.skyhanni.features.cosmetics
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.LorenzTickEvent
+import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
+import at.hannibal2.skyhanni.utils.LocationUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy
+import at.hannibal2.skyhanni.utils.LorenzUtils.toChromaColor
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine
+import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import net.minecraft.client.Minecraft
+import net.minecraftforge.client.event.RenderWorldLastEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.awt.Color
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
+
+class CosmeticFollowingLine {
+ private val config get() = SkyHanniMod.feature.misc.cosmeticConfig.followingLineConfig
+
+ private var locations = mapOf<LorenzVec, LocationSpot>()
+ private var latestLocations = mapOf<LorenzVec, LocationSpot>()
+
+ class LocationSpot(val time: SimpleTimeMark, val onGround: Boolean)
+
+ @SubscribeEvent
+ fun onWorldChange(event: LorenzWorldChangeEvent) {
+ locations = emptyMap()
+ }
+
+ @SubscribeEvent
+ fun onRenderWorld(event: RenderWorldLastEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.enabled) return
+
+ updateClose(event)
+
+ val firstPerson = Minecraft.getMinecraft().gameSettings.thirdPersonView == 0
+ val color = config.lineColor.toChromaColor()
+
+ renderClose(event, firstPerson, color)
+ renderFar(event, firstPerson, color)
+ }
+
+ private fun renderFar(
+ event: RenderWorldLastEvent,
+ firstPerson: Boolean,
+ color: Color
+ ) {
+ val last7 = locations.keys.toList().takeLast(7)
+ val last2 = locations.keys.toList().takeLast(2)
+
+ for ((a, b) in locations.keys.zipWithNext()) {
+ val locationSpot = locations[b]!!
+ if (firstPerson) {
+ if (!locationSpot.onGround) {
+ if (b in last7) {
+ // Do not render the line in the face, keep more distance while the line is in the air
+ continue
+ }
+ }
+ }
+ if (b in last2) {
+ if (locationSpot.time.passedSince() < 400.milliseconds) {
+ // Do not render the line directly next to the player, prevent laggy design
+ continue
+ }
+ }
+ event.draw3DLine(a, b, color, locationSpot.getWidth(), !config.behindBlocks)
+ }
+ }
+
+ private fun updateClose(event: RenderWorldLastEvent) {
+ val playerLocation = event.exactLocation(Minecraft.getMinecraft().thePlayer).add(0.0, 0.3, 0.0)
+
+ latestLocations = latestLocations.editCopy {
+ val locationSpot = LocationSpot(SimpleTimeMark.now(), Minecraft.getMinecraft().thePlayer.onGround)
+ this[playerLocation] = locationSpot
+ values.removeIf { it.time.passedSince() > 600.milliseconds }
+ }
+ }
+
+ private fun renderClose(event: RenderWorldLastEvent, firstPerson: Boolean, color: Color) {
+ if (firstPerson && latestLocations.any { !it.value.onGround }) return
+
+ for ((a, b) in latestLocations.keys.zipWithNext()) {
+ val locationSpot = latestLocations[b]!!
+ event.draw3DLine(a, b, color, locationSpot.getWidth(), !config.behindBlocks)
+ }
+ }
+
+ private fun LocationSpot.getWidth(): Int {
+ val millis = time.passedSince().inWholeMilliseconds
+ val percentage = millis.toDouble() / (config.secondsAlive * 1000.0)
+ val maxWidth = config.lineWidth
+ val lineWidth = 1 + maxWidth - percentage * maxWidth
+ return lineWidth.toInt().coerceAtLeast(1)
+ }
+
+ @SubscribeEvent
+ fun onTick(event: LorenzTickEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.enabled) return
+
+ if (event.isMod(5)) {
+ locations = locations.editCopy { values.removeIf { it.time.passedSince() > config.secondsAlive.seconds } }
+
+ // Safety check to not cause lags
+ while (locations.size > 5_000) {
+ locations = locations.editCopy { remove(keys.first()) }
+ }
+ }
+
+ if (event.isMod(2)) {
+ val playerLocation = LocationUtils.playerLocation().add(0.0, 0.3, 0.0)
+
+ locations.keys.lastOrNull()?.let {
+ if (it.distance(playerLocation) < 0.1) return
+ }
+
+ locations = locations.editCopy {
+ this[playerLocation] = LocationSpot(SimpleTimeMark.now(), Minecraft.getMinecraft().thePlayer.onGround)
+ }
+ }
+ }
+}