Open-source multiplayer game server compatible with the RuneScape client https://www.openrs2.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
openrs2/cache/src/main/kotlin/org/openrs2/cache/OpenNxtStore.kt

89 lines
3.0 KiB

package org.openrs2.cache
import io.netty.buffer.Unpooled
import org.openrs2.buffer.crc32
import org.openrs2.buffer.use
import org.sqlite.SQLiteDataSource
import java.nio.file.Files
import java.nio.file.Path
import java.sql.Connection
public object OpenNxtStore {
public fun unpack(input: Path, output: Store) {
output.create(Store.ARCHIVESET)
for (archive in 0..Store.MAX_ARCHIVE) {
val path = input.resolve("js5-$archive.jcache")
if (!Files.exists(path)) {
continue
}
val dataSource = SQLiteDataSource()
dataSource.url = "jdbc:sqlite:$path"
dataSource.connection.use { connection ->
unpackArchive(connection, archive, output)
}
}
}
private fun unpackArchive(connection: Connection, archive: Int, output: Store) {
connection.prepareStatement(
"""
SELECT data, crc
FROM cache_index
WHERE key = 1
""".trimIndent()
).use { stmt ->
stmt.executeQuery().use { rows ->
if (rows.next()) {
val checksum = rows.getInt(2)
Unpooled.wrappedBuffer(rows.getBytes(1)).use { buf ->
val actualChecksum = buf.crc32()
if (actualChecksum != checksum) {
throw StoreCorruptException(
"Js5Index corrupt (expected checksum $checksum, actual checksum $actualChecksum)"
)
}
output.write(Store.ARCHIVESET, archive, buf)
}
}
}
}
connection.prepareStatement(
"""
SELECT key, data, crc, version
FROM cache
""".trimIndent()
).use { stmt ->
stmt.executeQuery().use { rows ->
while (rows.next()) {
val group = rows.getInt(1)
val checksum = rows.getInt(3)
val version = rows.getInt(4) and 0xFFFF
Unpooled.wrappedBuffer(rows.getBytes(2)).use { buf ->
val actualVersion = VersionTrailer.peek(buf)
if (actualVersion != version) {
throw StoreCorruptException(
"Group corrupt (expected version $version, actual version $actualVersion)"
)
}
val actualChecksum = buf.slice(buf.readerIndex(), buf.writerIndex() - 2).crc32()
if (actualChecksum != checksum) {
throw StoreCorruptException(
"Group corrupt (expected checksum $checksum, actual checksum $actualChecksum)"
)
}
output.write(archive, group, buf)
}
}
}
}
}
}