diff --git a/archive/src/main/kotlin/org/openrs2/archive/cache/CacheDownloader.kt b/archive/src/main/kotlin/org/openrs2/archive/cache/CacheDownloader.kt index 0855bdb9..7078bf71 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/cache/CacheDownloader.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/cache/CacheDownloader.kt @@ -2,6 +2,7 @@ package org.openrs2.archive.cache import dev.openrs2.net.BootstrapFactory import dev.openrs2.net.awaitSuspend +import org.openrs2.archive.game.GameDatabase import javax.inject.Inject import javax.inject.Singleton import kotlin.coroutines.suspendCoroutine @@ -9,14 +10,21 @@ import kotlin.coroutines.suspendCoroutine @Singleton public class CacheDownloader @Inject constructor( private val bootstrapFactory: BootstrapFactory, + private val gameDatabase: GameDatabase, private val importer: CacheImporter ) { - public suspend fun download(hostname: String, port: Int, version: Int) { + public suspend fun download(gameName: String) { + val game = gameDatabase.getGame(gameName) ?: throw Exception("Game not found") + + val hostname = game.hostname ?: throw Exception("Hostname not set") + val port = game.port ?: throw Exception("Port not set") + val build = game.build ?: throw Exception("Current build not set") + val group = bootstrapFactory.createEventLoopGroup() try { suspendCoroutine { continuation -> val bootstrap = bootstrapFactory.createBootstrap(group) - val handler = Js5ChannelHandler(bootstrap, hostname, port, version, continuation, importer) + val handler = Js5ChannelHandler(bootstrap, game.id, hostname, port, build, continuation, importer) bootstrap.handler(Js5ChannelInitializer(handler)) .connect(hostname, port) diff --git a/archive/src/main/kotlin/org/openrs2/archive/cache/CacheImporter.kt b/archive/src/main/kotlin/org/openrs2/archive/cache/CacheImporter.kt index 6badb3b6..d119f49c 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/cache/CacheImporter.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/cache/CacheImporter.kt @@ -127,9 +127,28 @@ public class CacheImporter @Inject constructor( } } - public suspend fun importMasterIndexAndGetIndexes(masterIndex: Js5MasterIndex, buf: ByteBuf): List { + public suspend fun importMasterIndexAndGetIndexes( + masterIndex: Js5MasterIndex, + buf: ByteBuf, + gameId: Int, + build: Int + ): List { return database.execute { connection -> prepare(connection) + + connection.prepareStatement( + """ + UPDATE games + SET build = ? + WHERE id = ? + """.trimIndent() + ).use { stmt -> + stmt.setInt(1, build) + stmt.setInt(2, gameId) + + stmt.execute() + } + addMasterIndex(connection, MasterIndex(masterIndex, buf)) connection.prepareStatement( diff --git a/archive/src/main/kotlin/org/openrs2/archive/cache/DownloadCommand.kt b/archive/src/main/kotlin/org/openrs2/archive/cache/DownloadCommand.kt index 984838f0..5a719670 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/cache/DownloadCommand.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/cache/DownloadCommand.kt @@ -1,15 +1,18 @@ package org.openrs2.archive.cache import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.parameters.arguments.argument +import com.github.ajalt.clikt.parameters.arguments.default import com.google.inject.Guice import kotlinx.coroutines.runBlocking import org.openrs2.archive.ArchiveModule public class DownloadCommand : CliktCommand(name = "download") { + private val game by argument().default("oldschool") + override fun run(): Unit = runBlocking { val injector = Guice.createInjector(ArchiveModule) val downloader = injector.getInstance(CacheDownloader::class.java) - // TODO(gpe): make these configurable and/or fetch from the database - downloader.download("oldschool1.runescape.com", 43594, 193) + downloader.download(game) } } diff --git a/archive/src/main/kotlin/org/openrs2/archive/cache/Js5ChannelHandler.kt b/archive/src/main/kotlin/org/openrs2/archive/cache/Js5ChannelHandler.kt index b4259eee..27f2284e 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/cache/Js5ChannelHandler.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/cache/Js5ChannelHandler.kt @@ -29,6 +29,7 @@ import kotlin.coroutines.resumeWithException @ChannelHandler.Sharable public class Js5ChannelHandler( private val bootstrap: Bootstrap, + private val gameId: Int, private val hostname: String, private val port: Int, private var version: Int, @@ -155,7 +156,7 @@ public class Js5ChannelHandler( Js5MasterIndex.read(uncompressed) } - val rawIndexes = runBlocking { importer.importMasterIndexAndGetIndexes(masterIndex!!, buf) } + val rawIndexes = runBlocking { importer.importMasterIndexAndGetIndexes(masterIndex!!, buf, gameId, version) } try { indexes = arrayOfNulls(rawIndexes.size) diff --git a/archive/src/main/kotlin/org/openrs2/archive/game/Game.kt b/archive/src/main/kotlin/org/openrs2/archive/game/Game.kt new file mode 100644 index 00000000..f4b71a8c --- /dev/null +++ b/archive/src/main/kotlin/org/openrs2/archive/game/Game.kt @@ -0,0 +1,8 @@ +package org.openrs2.archive.game + +public data class Game( + public val id: Int, + public val hostname: String?, + public val port: Int?, + public val build: Int? +) diff --git a/archive/src/main/kotlin/org/openrs2/archive/game/GameDatabase.kt b/archive/src/main/kotlin/org/openrs2/archive/game/GameDatabase.kt new file mode 100644 index 00000000..ef6ac886 --- /dev/null +++ b/archive/src/main/kotlin/org/openrs2/archive/game/GameDatabase.kt @@ -0,0 +1,45 @@ +package org.openrs2.archive.game + +import org.openrs2.db.Database +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +public class GameDatabase @Inject constructor( + private val database: Database +) { + public suspend fun getGame(name: String): Game? { + return database.execute { connection -> + connection.prepareStatement( + """ + SELECT id, hostname, port, build + FROM games + WHERE name = ? + """.trimIndent() + ).use { stmt -> + stmt.setString(1, name) + + stmt.executeQuery().use { rows -> + if (!rows.next()) { + return@execute null + } + + val id = rows.getInt(1) + val hostname: String? = rows.getString(2) + + var port: Int? = rows.getInt(3) + if (rows.wasNull()) { + port = null + } + + var build: Int? = rows.getInt(4) + if (rows.wasNull()) { + build = null + } + + return@execute Game(id, hostname, port, build) + } + } + } + } +} diff --git a/archive/src/main/resources/org/openrs2/archive/V1__init.sql b/archive/src/main/resources/org/openrs2/archive/V1__init.sql index 74a99b8c..a7f928a6 100644 --- a/archive/src/main/resources/org/openrs2/archive/V1__init.sql +++ b/archive/src/main/resources/org/openrs2/archive/V1__init.sql @@ -1,6 +1,19 @@ -- @formatter:off CREATE EXTENSION uint; +CREATE TABLE games ( + id SERIAL PRIMARY KEY NOT NULL, + name TEXT UNIQUE NOT NULL, + hostname TEXT NULL, + port uint2 NULL, + build INTEGER NULL +); + +INSERT INTO games (name, hostname, port, build) +VALUES + ('runescape', NULL, NULL, NULL), + ('oldschool', 'oldschool1.runescape.com', 43594, 193); + CREATE TYPE xtea_key AS ( k0 INTEGER, k1 INTEGER,