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.
85 lines
3.0 KiB
85 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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|