aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/utils')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ComputerTimeOffset.kt122
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt13
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 {