Skip to content

Commit 6b41e6c

Browse files
committed
check for offline players & optimization
1 parent 8d07727 commit 6b41e6c

File tree

4 files changed

+37
-8
lines changed

4 files changed

+37
-8
lines changed

src/main/java/ua/mei/minekord/mixin/ServerLoginNetworkHandlerMixin.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package ua.mei.minekord.mixin;
22

33
import com.mojang.authlib.GameProfile;
4-
import net.minecraft.network.ClientConnection;
54
import net.minecraft.network.packet.c2s.login.LoginHelloC2SPacket;
6-
import net.minecraft.network.packet.s2c.login.LoginHelloS2CPacket;
7-
import net.minecraft.network.packet.s2c.login.LoginSuccessS2CPacket;
85
import net.minecraft.server.MinecraftServer;
96
import net.minecraft.server.network.ServerLoginNetworkHandler;
107
import net.minecraft.text.Text;
@@ -27,16 +24,23 @@ public abstract class ServerLoginNetworkHandlerMixin {
2724

2825
@Shadow protected abstract void sendSuccessPacket(GameProfile gameProfile);
2926

27+
@Shadow @Final MinecraftServer server;
28+
3029
@Inject(method = "onHello", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;isOnlineMode()Z"), cancellable = true)
3130
private void minekord$trueUuids(LoginHelloC2SPacket loginHelloC2SPacket, CallbackInfo ci) {
3231
if (SnowflakeToUUID.INSTANCE.enabled()) {
32+
if (this.server.isOnlineMode() && !SnowflakeToUUID.INSTANCE.allowOfflinePlayers() && !SnowflakeToUUID.INSTANCE.premiumPlayer(loginHelloC2SPacket.comp_907())) {
33+
this.disconnect(Text.literal("test1"));
34+
ci.cancel();
35+
}
36+
3337
UUID trueUuid = SnowflakeToUUID.INSTANCE.generateFromNickname(loginHelloC2SPacket.comp_765());
3438

3539
if (trueUuid != null) {
3640
this.profile = new GameProfile(trueUuid, loginHelloC2SPacket.comp_765());
37-
sendSuccessPacket(this.profile);
41+
this.sendSuccessPacket(this.profile);
3842
} else {
39-
this.disconnect(Text.literal("lol"));
43+
this.disconnect(Text.literal("test2"));
4044
}
4145

4246
ci.cancel();

src/main/kotlin/ua/mei/minekord/auth/SnowflakeToUUID.kt

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,42 @@ package ua.mei.minekord.auth
22

33
import dev.kord.common.annotation.KordExperimental
44
import dev.kord.core.entity.Member
5+
import io.ktor.client.HttpClient
6+
import io.ktor.client.engine.okhttp.OkHttp
7+
import io.ktor.client.plugins.timeout
8+
import io.ktor.client.request.get
9+
import io.ktor.client.statement.HttpResponse
10+
import io.ktor.http.HttpStatusCode
511
import kotlinx.coroutines.flow.filter
612
import kotlinx.coroutines.flow.firstOrNull
713
import kotlinx.coroutines.runBlocking
814
import ua.mei.minekord.bot.MinekordBot
915
import ua.mei.minekord.config.AuthSpec
1016
import ua.mei.minekord.config.config
1117
import java.util.UUID
18+
import kotlin.experimental.inv
1219

1320
object SnowflakeToUUID {
21+
private val client: HttpClient = HttpClient(OkHttp)
22+
1423
fun enabled(): Boolean = config[AuthSpec.uuidFromSnowflake]
24+
fun allowOfflinePlayers(): Boolean = config[AuthSpec.allowOfflinePlayers]
25+
26+
fun premiumPlayer(uuid: UUID): Boolean {
27+
return runBlocking {
28+
try {
29+
client.get("https://sessionserver.mojang.com/session/minecraft/profile/$uuid")
30+
.status == HttpStatusCode.OK
31+
} catch (_: Exception) {
32+
false
33+
}
34+
}
35+
}
1536

1637
@OptIn(KordExperimental::class)
1738
fun generateFromNickname(nickname: String): UUID? {
1839
return runBlocking {
19-
return@runBlocking try {
40+
try {
2041
val member: Member = MinekordBot.guild?.getMembers(nickname)?.filter {
2142
it.roleIds.map { it.value }.all { it in config[AuthSpec.requiredRoles] }
2243
}?.firstOrNull() ?: return@runBlocking null
@@ -29,8 +50,8 @@ object SnowflakeToUUID {
2950
}
3051

3152
fun generateFromId(discordId: ULong): UUID {
32-
val mostSigBytes: ByteArray = ByteArray(8) { i -> (discordId shr ((7 - i) * 8) and 0xFFu).toByte() }
33-
val leastSigBytes: ByteArray = ByteArray(8) { i -> ((ULong.MAX_VALUE - discordId) shr ((7 - i) * 8) and 0xFFu).toByte() }
53+
val mostSigBytes: ByteArray = ByteArray(8) { (discordId shr ((7 - it) * 8) and 0xFFu).toByte() }
54+
val leastSigBytes: ByteArray = mostSigBytes.map { it.inv() }.toByteArray()
3455

3556
val mostSigBits: Long = mostSigBytes.fold(0L) { acc, byte -> (acc shl 8) or (byte.toLong() and 0xFF) }
3657
val leastSigBits: Long = leastSigBytes.fold(0L) { acc, byte -> (acc shl 8) or (byte.toLong() and 0xFF) }

src/main/kotlin/ua/mei/minekord/config/AuthSpec.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ import com.uchuhimo.konf.ConfigSpec
44

55
object AuthSpec : ConfigSpec() {
66
val uuidFromSnowflake by required<Boolean>()
7+
val allowOfflinePlayers by required<Boolean>()
78
val requiredRoles by required<List<ULong>>()
89
}

src/main/resources/minekord.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ chat = 0
1111
# Works with offline and online mode.
1212
uuidFromSnowflake = false
1313

14+
# If true, offline players can join server if online mode enabled.
15+
allowOfflinePlayers = false
16+
1417
# Roles which required for server join.
1518
# Can be empty.
1619
requiredRoles = []

0 commit comments

Comments
 (0)