diff --git a/cache/src/main/kotlin/org/openrs2/cache/Js5MasterIndex.kt b/cache/src/main/kotlin/org/openrs2/cache/Js5MasterIndex.kt index 3ffcc75c..8107dc94 100644 --- a/cache/src/main/kotlin/org/openrs2/cache/Js5MasterIndex.kt +++ b/cache/src/main/kotlin/org/openrs2/cache/Js5MasterIndex.kt @@ -1,6 +1,8 @@ package org.openrs2.cache import io.netty.buffer.ByteBuf +import org.openrs2.buffer.crc32 +import org.openrs2.buffer.use public inline class Js5MasterIndex(public val entries: MutableList = mutableListOf()) { public data class Entry(public var version: Int, public var checksum: Int) @@ -13,6 +15,34 @@ public inline class Js5MasterIndex(public val entries: MutableList = muta } public companion object { + public fun create(store: Store): Js5MasterIndex { + val index = Js5MasterIndex() + + var nextArchive = 0 + for (archive in store.list(Js5Archive.ARCHIVESET)) { + /* + * Fill in gaps with zeroes. I think this is consistent with + * the official implementation: the TFU client warns that + * entries with a zero CRC are probably invalid. + */ + for (i in nextArchive until archive) { + index.entries += Entry(0, 0) + } + + val entry = store.read(Js5Archive.ARCHIVESET, archive).use { buf -> + val checksum = buf.crc32() + val version = Js5Index.read(buf).version + // TODO(gpe): should we throw an exception if there are trailing bytes here? + Entry(version, checksum) + } + + index.entries += entry + nextArchive = archive + 1 + } + + return index + } + public fun read(buf: ByteBuf): Js5MasterIndex { require(buf.readableBytes() % 8 == 0) diff --git a/cache/src/test/kotlin/org/openrs2/cache/Js5MasterIndexTest.kt b/cache/src/test/kotlin/org/openrs2/cache/Js5MasterIndexTest.kt new file mode 100644 index 00000000..49244d24 --- /dev/null +++ b/cache/src/test/kotlin/org/openrs2/cache/Js5MasterIndexTest.kt @@ -0,0 +1,26 @@ +package org.openrs2.cache + +import java.nio.file.Paths +import kotlin.test.Test +import kotlin.test.assertEquals + +object Js5MasterIndexTest { + private val ROOT = Paths.get(FlatFileStoreTest::class.java.getResource("master-index").toURI()) + + @Test + fun testCreate() { + val index = Store.open(ROOT).use { store -> + Js5MasterIndex.create(store) + } + + assertEquals(Js5MasterIndex(mutableListOf( + Js5MasterIndex.Entry(0, 379203374), + Js5MasterIndex.Entry(0x12345678, -717247318), + Js5MasterIndex.Entry(0, 0), + Js5MasterIndex.Entry(0x9ABCDEF0.toInt(), 895417101), + Js5MasterIndex.Entry(0, 0), + Js5MasterIndex.Entry(0, 0), + Js5MasterIndex.Entry(0xAA55AA55.toInt(), -627983571) + )), index) + } +} diff --git a/cache/src/test/resources/org/openrs2/cache/master-index/255/0.dat b/cache/src/test/resources/org/openrs2/cache/master-index/255/0.dat new file mode 100644 index 00000000..a786e127 Binary files /dev/null and b/cache/src/test/resources/org/openrs2/cache/master-index/255/0.dat differ diff --git a/cache/src/test/resources/org/openrs2/cache/master-index/255/1.dat b/cache/src/test/resources/org/openrs2/cache/master-index/255/1.dat new file mode 100644 index 00000000..a8c24c5d Binary files /dev/null and b/cache/src/test/resources/org/openrs2/cache/master-index/255/1.dat differ diff --git a/cache/src/test/resources/org/openrs2/cache/master-index/255/3.dat b/cache/src/test/resources/org/openrs2/cache/master-index/255/3.dat new file mode 100644 index 00000000..540f4779 Binary files /dev/null and b/cache/src/test/resources/org/openrs2/cache/master-index/255/3.dat differ diff --git a/cache/src/test/resources/org/openrs2/cache/master-index/255/6.dat b/cache/src/test/resources/org/openrs2/cache/master-index/255/6.dat new file mode 100644 index 00000000..35a00753 Binary files /dev/null and b/cache/src/test/resources/org/openrs2/cache/master-index/255/6.dat differ