|
|
|
package org.openrs2.archive.cache
|
|
|
|
|
|
|
|
import org.openrs2.archive.cache.nxt.MusicStreamClient
|
|
|
|
import org.openrs2.archive.game.GameDatabase
|
|
|
|
import org.openrs2.archive.jav.JavConfig
|
|
|
|
import org.openrs2.buffer.ByteBufBodyHandler
|
|
|
|
import org.openrs2.net.BootstrapFactory
|
|
|
|
import org.openrs2.net.awaitSuspend
|
|
|
|
import java.net.URI
|
|
|
|
import java.net.http.HttpClient
|
|
|
|
import javax.inject.Inject
|
|
|
|
import javax.inject.Singleton
|
|
|
|
import kotlin.coroutines.suspendCoroutine
|
|
|
|
|
|
|
|
@Singleton
|
|
|
|
public class CacheDownloader @Inject constructor(
|
|
|
|
private val client: HttpClient,
|
|
|
|
private val byteBufBodyHandler: ByteBufBodyHandler,
|
|
|
|
private val bootstrapFactory: BootstrapFactory,
|
|
|
|
private val gameDatabase: GameDatabase,
|
|
|
|
private val importer: CacheImporter
|
|
|
|
) {
|
|
|
|
public suspend fun download(gameName: String) {
|
|
|
|
val game = gameDatabase.getGame(gameName) ?: throw Exception("Game not found")
|
|
|
|
|
|
|
|
val url = game.url ?: throw Exception("URL not set")
|
|
|
|
val buildMajor = game.buildMajor ?: throw Exception("Current major build not set")
|
|
|
|
|
|
|
|
val config = JavConfig.download(client, url)
|
|
|
|
|
|
|
|
val group = bootstrapFactory.createEventLoopGroup()
|
|
|
|
try {
|
|
|
|
suspendCoroutine<Unit> { continuation ->
|
|
|
|
val bootstrap = bootstrapFactory.createBootstrap(group)
|
|
|
|
|
|
|
|
val hostname: String
|
|
|
|
|
|
|
|
val initializer = when (gameName) {
|
|
|
|
"oldschool" -> {
|
|
|
|
val codebase = config.config[CODEBASE] ?: throw Exception("Codebase missing")
|
|
|
|
hostname = URI(codebase).host ?: throw Exception("Hostname missing")
|
|
|
|
|
|
|
|
OsrsJs5ChannelInitializer(
|
|
|
|
OsrsJs5ChannelHandler(
|
|
|
|
bootstrap,
|
|
|
|
game.id,
|
|
|
|
hostname,
|
|
|
|
PORT,
|
|
|
|
buildMajor,
|
|
|
|
game.lastMasterIndexId,
|
|
|
|
continuation,
|
|
|
|
importer,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
"runescape" -> {
|
|
|
|
val buildMinor = game.buildMinor ?: throw Exception("Current minor build not set")
|
|
|
|
|
|
|
|
val tokens = config.params.values.filter { TOKEN_REGEX.matches(it) }
|
|
|
|
val token = tokens.singleOrNull() ?: throw Exception("Multiple candidate tokens: $tokens")
|
|
|
|
|
|
|
|
hostname = NXT_HOSTNAME
|
|
|
|
|
|
|
|
val musicStreamClient = MusicStreamClient(client, byteBufBodyHandler, "http://$hostname")
|
|
|
|
|
|
|
|
NxtJs5ChannelInitializer(
|
|
|
|
NxtJs5ChannelHandler(
|
|
|
|
bootstrap,
|
|
|
|
game.id,
|
|
|
|
hostname,
|
|
|
|
PORT,
|
|
|
|
buildMajor,
|
|
|
|
buildMinor,
|
|
|
|
game.lastMasterIndexId,
|
|
|
|
continuation,
|
|
|
|
importer,
|
|
|
|
token,
|
|
|
|
musicStreamClient
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
else -> throw UnsupportedOperationException()
|
|
|
|
}
|
|
|
|
|
|
|
|
bootstrap.handler(initializer)
|
|
|
|
.connect(hostname, PORT)
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
group.shutdownGracefully().awaitSuspend()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private companion object {
|
|
|
|
private const val CODEBASE = "codebase"
|
|
|
|
private const val NXT_HOSTNAME = "content.runescape.com"
|
|
|
|
private const val PORT = 443
|
|
|
|
private val TOKEN_REGEX = Regex("[A-Za-z0-9*-]{32}")
|
|
|
|
}
|
|
|
|
}
|