blob: 83ea15ecc437846f8bb4241710f02c3f7d6aa097 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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())
}
}
}
|