Skip to content

Commit

Permalink
feat(shulker-proxy-agent): query mojang api to get unknown player nam…
Browse files Browse the repository at this point in the history
…es or ids
  • Loading branch information
jeremylvln committed Oct 28, 2023
1 parent b1351ec commit e7eb734
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import io.shulkermc.proxyagent.adapters.filesystem.FileSystemAdapter
import io.shulkermc.proxyagent.adapters.filesystem.LocalFileSystemAdapter
import io.shulkermc.proxyagent.adapters.kubernetes.KubernetesGatewayAdapter
import io.shulkermc.proxyagent.adapters.kubernetes.ImplKubernetesGatewayAdapter
import io.shulkermc.proxyagent.adapters.mojang.HttpMojangGatewayAdapter
import io.shulkermc.proxyagent.adapters.mojang.MojangGatewayAdapter
import io.shulkermc.proxyagent.adapters.pubsub.PubSubAdapter
import io.shulkermc.proxyagent.adapters.pubsub.RedisPubSubAdapter
import io.shulkermc.proxyagent.api.ShulkerProxyAPI
Expand All @@ -30,6 +32,7 @@ class ShulkerProxyAgentCommon(val proxyInterface: ProxyInterface, val logger: Lo
// Adapters
lateinit var kubernetesGateway: KubernetesGatewayAdapter
lateinit var fileSystem: FileSystemAdapter
lateinit var mojangGateway: MojangGatewayAdapter
lateinit var cache: CacheAdapter
lateinit var pubSub: PubSubAdapter

Expand All @@ -52,8 +55,9 @@ class ShulkerProxyAgentCommon(val proxyInterface: ProxyInterface, val logger: Lo
this.jedisPool = this.createJedisPool()
this.jedisPool.resource.use { jedis -> jedis.ping() }

this.fileSystem = LocalFileSystemAdapter()
this.kubernetesGateway = ImplKubernetesGatewayAdapter(Configuration.PROXY_NAMESPACE, Configuration.PROXY_NAME)
this.fileSystem = LocalFileSystemAdapter()
this.mojangGateway = HttpMojangGatewayAdapter()
this.cache = RedisCacheAdapter(this.jedisPool)
this.pubSub = RedisPubSubAdapter(this.jedisPool)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.shulkermc.proxyagent.adapters.mojang

import com.google.gson.JsonObject
import com.google.gson.JsonParser
import java.net.HttpURLConnection
import java.net.URI
import java.util.Optional
import java.util.UUID

class HttpMojangGatewayAdapter : MojangGatewayAdapter {
override fun getProfileFromName(playerName: String): Optional<MojangGatewayAdapter.MojangProfile> {
val url = URI("https://api.mojang.com/users/profiles/minecraft/$playerName").toURL()
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET"

val status = connection.responseCode
if (status != 200) return Optional.empty()

val response = connection.inputStream.bufferedReader().use { it.readText() }
val responseJson = JsonParser.parseString(response).asJsonObject
return Optional.of(this.getProfileFromJson(responseJson))
}

override fun getProfileFromId(playerId: UUID): Optional<MojangGatewayAdapter.MojangProfile> {
val undashedPlayerId = playerId.toString().replace("-", "")
val url = URI("https://sessionserver.mojang.com/session/minecraft/profile/$undashedPlayerId").toURL()
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET"

val status = connection.responseCode
if (status != 200) return Optional.empty()

val response = connection.inputStream.bufferedReader().use { it.readText() }
val responseJson = JsonParser.parseString(response).asJsonObject
return Optional.of(this.getProfileFromJson(responseJson))
}

private fun getProfileFromJson(json: JsonObject): MojangGatewayAdapter.MojangProfile {
val uuid = UUID.fromString(
json.get("id").asString.replaceFirst(
"(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)",
"$1-$2-$3-$4-$5"
)
)
val name = json.get("name").asString

return MojangGatewayAdapter.MojangProfile(uuid, name)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.shulkermc.proxyagent.adapters.mojang

import java.util.Optional
import java.util.UUID

interface MojangGatewayAdapter {
fun getProfileFromName(playerName: String): Optional<MojangProfile>
fun getProfileFromId(playerId: UUID): Optional<MojangProfile>

data class MojangProfile(val playerId: UUID, val playerName: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,33 @@ class ShulkerProxyAPIImpl(private val agent: ShulkerProxyAgentCommon) : ShulkerP

override fun getPlayerPosition(playerId: UUID): Optional<PlayerPosition> = this.agent.cache.getPlayerPosition(playerId)
override fun isPlayerConnected(playerId: UUID): Boolean = this.agent.cache.isPlayerConnected(playerId)
override fun countOnlinePlayers(): Int = this.agent.cache.countOnlinePlayers()

override fun getPlayerIdFromName(playerName: String): Optional<UUID> {
val cachedValue = this.agent.cache.getPlayerIdFromName(playerName)
if (cachedValue.isPresent) return cachedValue

val mojangProfile = this.agent.mojangGateway.getProfileFromName(playerName)
if (mojangProfile.isPresent) {
val playerId = mojangProfile.get().playerId
this.agent.cache.updateCachedPlayerName(playerId, playerName)
return Optional.of(playerId)
}

return Optional.empty()
}

override fun getPlayerNameFromId(playerId: UUID): Optional<String> {
val cachedValue = this.agent.cache.getPlayerNameFromId(playerId)
if (cachedValue.isPresent) return cachedValue

val mojangProfile = this.agent.mojangGateway.getProfileFromId(playerId)
if (mojangProfile.isPresent) {
val playerName = mojangProfile.get().playerName
this.agent.cache.updateCachedPlayerName(playerId, playerName)
return Optional.of(playerName)
}

return Optional.empty()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
public abstract class ShulkerProxyAPI {
public static ShulkerProxyAPI INSTANCE;

abstract public Set<String> getServersByTag(@NotNull String tag);
abstract public @NotNull Set<String> getServersByTag(@NotNull String tag);

abstract public Optional<PlayerPosition> getPlayerPosition(@NotNull UUID playerId);
abstract public @NotNull Optional<PlayerPosition> getPlayerPosition(@NotNull UUID playerId);
abstract public boolean isPlayerConnected(@NotNull UUID playerId);
abstract public int countOnlinePlayers();

abstract public @NotNull Optional<UUID> getPlayerIdFromName(@NotNull String playerName);
abstract public @NotNull Optional<String> getPlayerNameFromId(@NotNull UUID playerId);

public record PlayerPosition(@NotNull String proxyName, @NotNull String serverName) {}
}

0 comments on commit e7eb734

Please sign in to comment.