diff options
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/utils')
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/utils/ComputerTimeOffset.kt | 122 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt | 13 |
2 files changed, 134 insertions, 1 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ComputerTimeOffset.kt b/src/main/java/at/hannibal2/skyhanni/utils/ComputerTimeOffset.kt new file mode 100644 index 000000000..83ea15ecc --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/ComputerTimeOffset.kt @@ -0,0 +1,122 @@ +package at.hannibal2.skyhanni.utils + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.DebugDataCollectEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.TimeUtils.format +import kotlinx.coroutines.launch +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.apache.commons.net.ntp.NTPUDPClient +import java.net.InetAddress +import kotlin.concurrent.thread +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds + +@SkyHanniModule +object ComputerTimeOffset { + private var offsetMillis: Duration? = null + + private val config get() = SkyHanniMod.feature.misc.warnAboutPcTimeOffset + + private val offsetFixLinks by lazy { + when { + OSUtils.isWindows -> { + "https://support.microsoft.com/en-us/windows/how-to-set-your-time-and-time-zone-dfaa7122-479f-5b98-2a7b-fa0b6e01b261" + } + + OSUtils.isLinux -> "https://unix.stackexchange.com/a/79116" + OSUtils.isMac -> "https://support.apple.com/guide/mac-help/set-the-date-and-time-automatically-mchlp2996/mac" + else -> null + } + } + + init { + thread { + while (true) { + Thread.sleep(1000) + detectTimeChange() + } + } + } + + private fun checkOffset() { + val wasOffsetBefore = (offsetMillis?.absoluteValue ?: 0.seconds) > 5.seconds + SkyHanniMod.coroutineScope.launch { + offsetMillis = getNtpOffset("time.google.com") + offsetMillis?.let { + tryDisplayOffset(wasOffsetBefore) + } + } + } + + private fun getNtpOffset(ntpServer: String): Duration? = try { + val client = NTPUDPClient() + val address = InetAddress.getByName(ntpServer) + val timeInfo = client.getTime(address) + + timeInfo.computeDetails() + timeInfo.offset.milliseconds + } catch (e: Exception) { + if (LorenzUtils.inSkyBlock && config) ErrorManager.logErrorWithData( + e, "Failed to get NTP offset", + "server" to ntpServer, + ) + else e.printStackTrace() + null + } + + private var lastSystemTime = System.currentTimeMillis() + + private fun detectTimeChange() { + val currentSystemTime = System.currentTimeMillis() + val timeDifference = (currentSystemTime - lastSystemTime).milliseconds + lastSystemTime = currentSystemTime + + val expectedDuration = 1.seconds + val deviation = timeDifference - expectedDuration + + if (deviation.absoluteValue > 1.seconds) { + checkOffset() + } + } + + @SubscribeEvent + fun onProfileJoin(event: ProfileJoinEvent) { + DelayedRun.runDelayed(5.seconds) { + checkOffset() + } + } + + private fun tryDisplayOffset(wasOffsetBefore: Boolean) { + if (!config || !LorenzUtils.onHypixel) return + val offsetMillis = offsetMillis ?: return + if (offsetMillis.absoluteValue < 5.seconds) { + if (wasOffsetBefore) { + ChatUtils.chat("Congratulations! Your computer's clock is now accurate.") + } + return + } + + ChatUtils.clickableLinkChat( + "Your computer's clock is off by ${offsetMillis.absoluteValue.format()}.\n" + + "§ePlease update your time settings. Many features may not function correctly until you do.\n" + + "§eClick here for instructions on how to fix your clock.", + offsetFixLinks ?: return, + prefixColor = "§c", + ) + } + + @SubscribeEvent + fun onDebugCollect(event: DebugDataCollectEvent) { + event.title("Time Offset") + val relevant = offsetMillis?.absoluteValue?.let { it < 100.milliseconds } ?: true + if (relevant) { + event.addData(offsetMillis.toString()) + } else { + event.addIrrelevant(offsetMillis.toString()) + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt index e209e0ce9..5b42c5dc6 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt @@ -7,6 +7,17 @@ import java.net.URI object OSUtils { + val isWindows: Boolean + val isMac: Boolean + val isLinux: Boolean + + init { + val os = System.getProperty("os.name") + isWindows = os.contains("win", ignoreCase = true) + isMac = os.contains("mac", ignoreCase = true) + isLinux = os.contains("linux", ignoreCase = true) + } + @JvmStatic fun openBrowser(url: String) { val desktopSupported = Desktop.isDesktopSupported() @@ -17,7 +28,7 @@ object OSUtils { } catch (e: IOException) { ErrorManager.logErrorWithData( e, "Error while opening website.", - "url" to url + "url" to url, ) } } else { |