But actually though this time

This commit is contained in:
woahscam 2021-10-28 15:19:20 -04:00
parent c75fa8e8c9
commit 9c67d6d9da
43 changed files with 3844 additions and 0 deletions

40
src/main/kotlin/cacheops/cache/Cache.kt vendored Normal file
View file

@ -0,0 +1,40 @@
package cacheops.cache
import com.displee.cache.index.Index255
import java.math.BigInteger
interface Cache {
var index255: Index255?
fun getFile(index: Int, archive: Int, file: Int = 0, xtea: IntArray? = null): ByteArray?
fun getFile(index: Int, name: String, xtea: IntArray? = null): ByteArray?
fun getArchive(indexId: Int, archiveId: Int): ByteArray?
fun generateOldVersionTable(): ByteArray
fun generateNewVersionTable(exponent: BigInteger, modulus: BigInteger): ByteArray
fun close()
fun getIndexCrc(indexId: Int): Int
fun archiveCount(indexId: Int, archiveId: Int): Int
fun lastFileId(indexId: Int, archive: Int): Int
fun lastArchiveId(indexId: Int): Int
fun getArchiveId(index: Int, name: String): Int
fun getArchiveId(index: Int, archive: Int): Int
fun getArchives(index: Int): IntArray
fun write(index: Int, archive: Int, file: Int, data: ByteArray, xteas: IntArray? = null)
fun update(): Boolean
}

View file

@ -0,0 +1,88 @@
package cacheops.cache
import com.displee.cache.CacheLibrary
import com.displee.cache.index.Index255
import java.math.BigInteger
class CacheDelegate(directory: String) : Cache {
private val delegate = CacheLibrary(directory)
init {
println("Cache read from $directory")
}
override var index255: Index255?
get() = delegate.index255
set(value) {
delegate.index255 = value
}
override fun getFile(index: Int, archive: Int, file: Int, xtea: IntArray?) =
delegate.data(index, archive, file, xtea)
override fun getFile(index: Int, name: String, xtea: IntArray?) = delegate.data(index, name, xtea)
override fun getArchive(indexId: Int, archiveId: Int): ByteArray? {
val index = if (indexId == 255) index255 else delegate.index(indexId)
if (index == null) {
println("Unable to find valid index for file request [indexId=$indexId, archiveId=$archiveId]}")
return null
}
val archiveSector = index.readArchiveSector(archiveId)
if (archiveSector == null) {
println("Unable to read archive sector $archiveId in index $indexId")
return null
}
return archiveSector.data
}
override fun generateOldVersionTable(): ByteArray = delegate.generateOldUkeys()
override fun generateNewVersionTable(exponent: BigInteger, modulus: BigInteger) = delegate.generateNewUkeys(exponent, modulus)
override fun close() = delegate.close()
override fun getIndexCrc(indexId: Int): Int {
return delegate.index(indexId).crc
}
override fun archiveCount(indexId: Int, archiveId: Int): Int {
return delegate.index(indexId).archive(archiveId)?.fileIds()?.size ?: 0
}
override fun lastFileId(indexId: Int, archive: Int): Int {
return delegate.index(indexId).archive(archive)?.last()?.id ?: -1
}
override fun lastArchiveId(indexId: Int): Int {
return delegate.index(indexId).last()?.id ?: 0
}
override fun getArchiveId(index: Int, name: String): Int {
return delegate.index(index).archiveId(name)
}
override fun getArchiveId(index: Int, hash: Int): Int {
delegate.index(index).archives().forEach { archive ->
if(archive.hashName == hash) {
return archive.id
}
}
return -1
}
override fun getArchives(index: Int): IntArray {
return delegate.index(index).archiveIds()
}
override fun write(index: Int, archive: Int, file: Int, data: ByteArray, xteas: IntArray?) {
delegate.put(index, archive, file, data, xteas)
}
override fun update(): Boolean {
delegate.update()
return true
}
}

View file

@ -0,0 +1,5 @@
package cacheops.cache
interface Definition {
var id: Int
}

View file

@ -0,0 +1,131 @@
package cacheops.cache
import cacheops.cache.buffer.read.BufferReader
import cacheops.cache.buffer.read.Reader
import java.util.concurrent.ConcurrentHashMap
abstract class DefinitionDecoder<T : Definition>(protected val cache: Cache, internal val index: Int) {
protected val dataCache = ConcurrentHashMap<Int, T>()
open val last: Int
get() = cache.lastArchiveId(index) * 256 + (cache.archiveCount(index, cache.lastArchiveId(index)))
val indices: IntRange
get() = 0..last
fun getOrNull(id: Int): T? {
var value = dataCache[id]
if (value == null) {
value = readData(id)
if (value != null) {
dataCache[id] = value
}
}
return value
}
open fun get(id: Int) = getOrNull(id) ?: create()
protected abstract fun create(): T
protected open fun getData(archive: Int, file: Int): ByteArray? {
return cache.getFile(index, archive, file)
}
protected open fun readData(id: Int): T? {
val archive = getArchive(id)
val file = getFile(id)
val data = getData(archive, file)
if (data != null) {
val definition = create()
definition.id = id
readLoop(definition, BufferReader(data))
definition.changeValues()
return definition
}
return null
}
protected open fun readLoop(definition: T, buffer: Reader) {
while (true) {
val opcode = buffer.readUnsignedByte()
if (opcode == 0) {
break
}
definition.read(opcode, buffer)
}
}
open fun getFile(id: Int) = id
open fun getArchive(id: Int) = id
protected abstract fun T.read(opcode: Int, buffer: Reader)
protected open fun T.changeValues() {
}
open fun clear() {
dataCache.clear()
}
fun forEach(function: (T) -> Unit) {
for (i in indices) {
val def = getOrNull(i) ?: continue
function.invoke(def)
}
}
companion object {
fun byteToChar(b: Byte): Char {
var i = 0xff and b.toInt()
require(i != 0) { "Non cp1252 character 0x" + i.toString(16) + " provided" }
if (i in 128..159) {
var char = UNICODE_TABLE[i - 128].toInt()
if (char == 0) {
char = 63
}
i = char
}
return i.toChar()
}
private var UNICODE_TABLE = charArrayOf(
'\u20ac',
'\u0000',
'\u201a',
'\u0192',
'\u201e',
'\u2026',
'\u2020',
'\u2021',
'\u02c6',
'\u2030',
'\u0160',
'\u2039',
'\u0152',
'\u0000',
'\u017d',
'\u0000',
'\u0000',
'\u2018',
'\u2019',
'\u201c',
'\u201d',
'\u2022',
'\u2013',
'\u2014',
'\u02dc',
'\u2122',
'\u0161',
'\u203a',
'\u0153',
'\u0000',
'\u017e',
'\u0178'
)
}
}

View file

@ -0,0 +1,7 @@
package cacheops.cache
import cacheops.cache.buffer.write.Writer
interface DefinitionEncoder<T : Definition> {
fun Writer.encode(definition: T)
}

View file

@ -0,0 +1,223 @@
package cacheops.cache.buffer.read
import java.nio.ByteBuffer
class BufferReader(
val buffer: ByteBuffer
) : Reader {
constructor(array: ByteArray) : this(buffer = ByteBuffer.wrap(array))
override val length: Int = buffer.remaining()
private var bitIndex = 0
override fun readByte(): Int {
return buffer.get().toInt()
}
override fun readByteAdd(): Int {
return (readByte() - 128).toByte().toInt()
}
override fun readByteInverse(): Int {
return -readByte()
}
override fun readByteSubtract(): Int {
return (readByteInverse() + 128).toByte().toInt()
}
override fun readUnsignedByte(): Int {
return readByte() and 0xff
}
override fun readShort(): Int {
return (readByte() shl 8) or readUnsignedByte()
}
override fun readShortAdd(): Int {
return (readByte() shl 8) or readUnsignedByteAdd()
}
override fun readUnsignedShortAdd(): Int {
return (readByte() shl 8) or ((readByte() - 128) and 0xff)
}
override fun readShortLittle(): Int {
return readUnsignedByte() or (readByte() shl 8)
}
override fun readShortAddLittle(): Int {
return readUnsignedByteAdd() or (readByte() shl 8)
}
override fun readUnsignedByteAdd(): Int {
return (readByte() - 128).toByte().toInt()
}
override fun readUnsignedShort(): Int {
return (readUnsignedByte() shl 8) or readUnsignedByte()
}
override fun readUnsignedShortLittle(): Int {
return readUnsignedByte() or (readUnsignedByte() shl 8)
}
override fun readMedium(): Int {
return (readByte() shl 16) or (readByte() shl 8) or readUnsignedByte()
}
override fun readUnsignedMedium(): Int {
return (readUnsignedByte() shl 16) or (readUnsignedByte() shl 8) or readUnsignedByte()
}
override fun readInt(): Int {
return (readUnsignedByte() shl 24) or (readUnsignedByte() shl 16) or (readUnsignedByte() shl 8) or readUnsignedByte()
}
override fun readIntInverseMiddle(): Int {
return (readByte() shl 16) or (readByte() shl 24) or readUnsignedByte() or (readByte() shl 8)
}
override fun readIntLittle(): Int {
return readUnsignedByte() or (readByte() shl 8) or (readByte() shl 16) or (readByte() shl 24)
}
override fun readUnsignedIntMiddle(): Int {
return (readUnsignedByte() shl 8) or readUnsignedByte() or (readUnsignedByte() shl 24) or (readUnsignedByte() shl 16)
}
override fun readSmart(): Int {
val peek = readUnsignedByte()
return if (peek < 128) {
peek and 0xFF
} else {
(peek shl 8 or readUnsignedByte()) - 32768
}
}
override fun readBigSmart(): Int {
val peek = readByte()
return if (peek < 0) {
((peek shl 24) or (readUnsignedByte() shl 16) or (readUnsignedByte() shl 8) or readUnsignedByte()) and 0x7fffffff
} else {
val value = (peek shl 8) or readUnsignedByte()
if (value == 32767) -1 else value
}
}
override fun readLargeSmart(): Int {
var baseValue = 0
var lastValue = readSmart()
while (lastValue == 32767) {
lastValue = readSmart()
baseValue += 32767
}
return baseValue + lastValue
}
override fun readLong(): Long {
val first = readInt().toLong() and 0xffffffffL
val second = readInt().toLong() and 0xffffffffL
return second + (first shl 32)
}
override fun readString(): String {
val sb = StringBuilder()
var b: Int
while (buffer.hasRemaining()) {
b = readByte()
if (b == 0) {
break
}
sb.append(b.toChar())
}
return sb.toString()
}
override fun readBytes(value: ByteArray) {
buffer.get(value)
}
override fun readBytes(array: ByteArray, offset: Int, length: Int) {
buffer.get(array, offset, length)
}
override fun skip(amount: Int) {
buffer.position(buffer.position() + amount)
}
override fun position(): Int {
return buffer.position()
}
override fun position(index: Int) {
buffer.position(index)
}
override fun array(): ByteArray {
return buffer.array()
}
override fun readableBytes(): Int {
return buffer.remaining()
}
override fun startBitAccess(): Reader {
bitIndex = buffer.position() * 8
return this
}
override fun finishBitAccess(): Reader {
buffer.position((bitIndex + 7) / 8)
return this
}
@Suppress("NAME_SHADOWING")
override fun readBits(bitCount: Int): Int {
if (bitCount < 0 || bitCount > 32) {
throw IllegalArgumentException("Number of bits must be between 1 and 32 inclusive")
}
var bitCount = bitCount
var bytePos = bitIndex shr 3
var bitOffset = 8 - (bitIndex and 7)
var value = 0
bitIndex += bitCount
while (bitCount > bitOffset) {
value += buffer.get(bytePos++).toInt() and BIT_MASKS[bitOffset] shl bitCount - bitOffset
bitCount -= bitOffset
bitOffset = 8
}
value += if (bitCount == bitOffset) {
buffer.get(bytePos).toInt() and BIT_MASKS[bitOffset]
} else {
buffer.get(bytePos).toInt() shr bitOffset - bitCount and BIT_MASKS[bitCount]
}
return value
}
fun readIncrSmallSmart(): Int {
var var3: Int = readSmart()
var value = 0
while (32767 == var3) {
var3 = readSmart()
value += 32767
}
value += var3
return value
}
companion object {
/**
* Bit masks for [readBits]
*/
private val BIT_MASKS = IntArray(32)
init {
for (i in BIT_MASKS.indices)
BIT_MASKS[i] = (1 shl i) - 1
}
}
}

View file

@ -0,0 +1,116 @@
package cacheops.cache.buffer.read
interface Reader {
/**
* Starting length of the packet
*/
val length: Int
fun readBoolean() = readByte() == 1
fun readBooleanAdd() = readByteAdd() == 1
fun readBooleanInverse() = readByteInverse() == 1
fun readBooleanSubtract() = readByteSubtract() == 1
fun readUnsignedBoolean() = readUnsignedByte() == 1
fun readByte(): Int
fun readByteAdd(): Int
fun readByteInverse(): Int
fun readByteSubtract(): Int
fun readUnsignedByte(): Int
fun readUnsignedByteAdd(): Int
fun readShort(): Int
fun readShortAdd(): Int
fun readShortLittle(): Int
fun readShortAddLittle(): Int
fun readUnsignedShort(): Int
fun readUnsignedShortLittle(): Int
fun readUnsignedShortAdd(): Int
fun readMedium(): Int
fun readUnsignedMedium(): Int
fun readInt(): Int
fun readIntInverseMiddle(): Int
fun readIntLittle(): Int
fun readUnsignedIntMiddle(): Int
fun readSmart(): Int
fun readBigSmart(): Int
fun readLargeSmart(): Int
fun readLong(): Long
fun readString(): String
/**
* Reads all bytes into [ByteArray]
* @param value The array to be written to.
*/
fun readBytes(value: ByteArray)
/**
* Reads [length] number of bytes starting at [offset] to [array].
* @param array The [ByteArray] to be written to
* @param offset Destination index
* @param length Number of bytes to read
*/
fun readBytes(array: ByteArray, offset: Int, length: Int = array.size)
/**
* Skips the [amount] bytes.
* @param amount Number of bytes to skip
*/
fun skip(amount: Int)
fun position(): Int
fun array(): ByteArray
fun position(index: Int)
/**
* Returns the remaining number of readable bytes.
* @return [Int]
*/
fun readableBytes(): Int
/**
* Enables individual decoded byte writing aka 'bit access'
*/
fun startBitAccess(): Reader
/**
* Disables 'bit access'
*/
fun finishBitAccess(): Reader
/**
* Writes a bit during 'bit access'
* @param bitCount number of bits to be written
* @param value bit value to be set
*/
fun readBits(bitCount: Int): Int
}

View file

@ -0,0 +1,206 @@
package cacheops.cache.buffer.write
import java.nio.ByteBuffer
/**
* All functions relative to writing directly to a packet are done by this class
*/
class BufferWriter(
capacity: Int = 64,
private val buffer: ByteBuffer = ByteBuffer.allocate(capacity)
) : Writer {
private var bitIndex = 0
override fun writeByte(value: Int) {
buffer.put(value.toByte())
}
override fun writeByteAdd(value: Int) {
writeByte(value + 128)
}
override fun writeByteInverse(value: Int) {
writeByte(-value)
}
override fun writeByteSubtract(value: Int) {
writeByte(-value + 128)
}
override fun setByte(index: Int, value: Int) {
buffer.put(index, value.toByte())
}
override fun writeShort(value: Int) {
writeByte(value shr 8)
writeByte(value)
}
override fun writeShortAdd(value: Int) {
writeByte(value shr 8)
writeByteAdd(value)
}
override fun writeShortLittle(value: Int) {
writeByte(value)
writeByte(value shr 8)
}
override fun writeShortAddLittle(value: Int) {
writeByteAdd(value)
writeByte(value shr 8)
}
override fun writeMedium(value: Int) {
writeByte(value shr 16)
writeByte(value shr 8)
writeByte(value)
}
override fun writeInt(value: Int) {
writeByte(value shr 24)
writeByte(value shr 16)
writeByte(value shr 8)
writeByte(value)
}
override fun writeIntMiddle(value: Int) {
writeByte(value shr 8)
writeByte(value)
writeByte(value shr 24)
writeByte(value shr 16)
}
override fun writeIntInverse(value: Int) {
writeByte(value shr 8)
writeByte(value shr 24)
writeByte(value shr 16)
writeByteInverse(value)
}
override fun writeIntInverseMiddle(value: Int) {
writeByte(value shr 16)
writeByte(value shr 24)
writeByte(value)
writeByte(value shr 8)
}
override fun writeIntLittle(value: Int) {
writeByte(value)
writeByte(value shr 8)
writeByte(value shr 16)
writeByte(value shr 24)
}
override fun writeIntInverseLittle(value: Int) {
writeByteInverse(value)
writeByte(value shr 8)
writeByte(value shr 16)
writeByte(value shr 24)
}
override fun writeLong(value: Long) {
writeByte((value shr 56).toInt())
writeByte((value shr 48).toInt())
writeByte((value shr 40).toInt())
writeByte((value shr 32).toInt())
writeByte((value shr 24).toInt())
writeByte((value shr 16).toInt())
writeByte((value shr 8).toInt())
writeByte(value.toInt())
}
override fun writeBytes(value: ByteArray) {
buffer.put(value)
}
override fun writeBytes(data: ByteArray, offset: Int, length: Int) {
buffer.put(data, offset, length)
}
override fun startBitAccess() {
bitIndex = buffer.position() * 8
}
override fun finishBitAccess() {
buffer.position((bitIndex + 7) / 8)
}
override fun writeBits(bitCount: Int, value: Boolean) {
writeBits(bitCount, if (value) 1 else 0)
}
override fun writeBits(bitCount: Int, value: Int) {
var numBits = bitCount
var byteIndex = bitIndex shr 3
var bitOffset = 8 - (bitIndex and 7)
bitIndex += numBits
var tmp: Int
var max: Int
while (numBits > bitOffset) {
tmp = buffer.get(byteIndex).toInt()
max = BIT_MASKS[bitOffset]
tmp = tmp and max.inv() or (value shr numBits - bitOffset and max)
buffer.put(byteIndex++, tmp.toByte())
numBits -= bitOffset
bitOffset = 8
}
tmp = buffer.get(byteIndex).toInt()
max = BIT_MASKS[numBits]
if (numBits == bitOffset) {
tmp = tmp and max.inv() or (value and max)
} else {
tmp = tmp and (max shl bitOffset - numBits).inv()
tmp = tmp or (value and max shl bitOffset - numBits)
}
buffer.put(byteIndex, tmp.toByte())
}
override fun position(): Int {
return buffer.position()
}
override fun position(index: Int) {
buffer.position(index)
}
override fun toArray(): ByteArray {
val data = ByteArray(position())
System.arraycopy(buffer.array(), 0, data, 0, data.size)
return data
}
override fun array(): ByteArray {
return buffer.array()
}
override fun clear() {
buffer.clear()
}
override fun remaining(): Int {
return buffer.remaining()
}
override fun writeIncrSmallSmart(value: Int) {
if (value < 128) {
writeByte(value)
} else {
writeShort(0x8000 or value)
}
}
companion object {
val BIT_MASKS = IntArray(32)
init {
for (i in BIT_MASKS.indices) {
BIT_MASKS[i] = (1 shl i) - 1
}
}
}
}

View file

@ -0,0 +1,101 @@
package cacheops.cache.buffer.write
/**
* All functions relative to writing directly to a packet are done by this class
*/
interface Writer {
fun setByte(index: Int, value: Int)
fun writeByte(value: Int)
fun writeByteAdd(value: Int)
fun writeByteInverse(value: Int)
fun writeByteSubtract(value: Int)
fun writeByte(value: Boolean) {
writeByte(if (value) 1 else 0)
}
fun writeShort(value: Int)
fun writeShortAdd(value: Int)
fun writeShortLittle(value: Int)
fun writeShortAddLittle(value: Int)
fun writeMedium(value: Int)
fun writeInt(value: Int)
fun writeIntMiddle(value: Int)
fun writeIntInverse(value: Int)
fun writeIntInverseMiddle(value: Int)
fun writeIntLittle(value: Int)
fun writeIntInverseLittle(value: Int)
fun writeLong(value: Long)
fun writeSmart(value: Int) {
if (value >= 128) {
writeShort(value + 32768)
} else {
writeByte(value)
}
}
fun writeString(value: String?) {
if (value != null) {
writeBytes(value.toByteArray())
}
writeByte(0)
}
fun writePrefixedString(value: String) {
writeByte(0)
writeBytes(value.toByteArray())
writeByte(0)
}
fun writeBytes(value: ByteArray)
fun writeBytes(data: ByteArray, offset: Int, length: Int)
fun startBitAccess()
fun finishBitAccess()
fun writeBits(bitCount: Int, value: Boolean) {
writeBits(bitCount, if (value) 1 else 0)
}
fun writeBits(bitCount: Int, value: Int)
fun skip(position: Int) {
for (i in 0 until position) {
writeByte(0)
}
}
fun position(): Int
fun position(index: Int)
fun toArray(): ByteArray
fun array(): ByteArray
fun clear()
fun remaining(): Int
fun writeIncrSmallSmart(value: Int)
}

View file

@ -0,0 +1,15 @@
package cacheops.cache.definition
import cacheops.cache.buffer.read.Reader
interface ColorPalette {
var recolourPalette: ByteArray?
fun readColourPalette(buffer: Reader) {
val length = buffer.readUnsignedByte()
recolourPalette = ByteArray(length)
repeat(length) { count ->
recolourPalette!![count] = buffer.readByte().toByte()
}
}
}

View file

@ -0,0 +1,16 @@
package cacheops.cache.definition
@Suppress("UNCHECKED_CAST")
interface Extra {
var extras: Map<String, Any>
operator fun <T: Any> get(key: String): T = extras.getValue(key) as T
fun has(key: String) = extras.containsKey(key)
fun getOrNull(key: String): Any? = extras[key]
operator fun <T : Any> get(key: String, defaultValue: T) = getOrNull(key) as? T ?: defaultValue
}

View file

@ -0,0 +1,28 @@
package cacheops.cache.definition
import cacheops.cache.buffer.read.Reader
@Suppress("UNCHECKED_CAST")
interface Parameterized {
var params: HashMap<Long, Any>?
fun <T : Any> getParam(key: Long) = params?.get(key) as T
fun <T : Any> getParamOrNull(key: Long) = params?.get(key) as? T
fun <T : Any> getParam(key: Long, default: T) = params?.get(key) as? T ?: default
fun readParameters(buffer: Reader) {
val length = buffer.readUnsignedByte()
if (length == 0) {
return
}
params = HashMap()
repeat(length) {
val string = buffer.readUnsignedBoolean()
val id = buffer.readUnsignedMedium().toLong()
params!![id] = if (string) buffer.readString() else buffer.readInt()
}
}
}

View file

@ -0,0 +1,30 @@
package cacheops.cache.definition
import cacheops.cache.buffer.read.Reader
interface Recolourable {
var originalColours: ShortArray?
var modifiedColours: ShortArray?
var originalTextureColours: ShortArray?
var modifiedTextureColours: ShortArray?
fun readColours(buffer: Reader) {
val length = buffer.readUnsignedByte()
originalColours = ShortArray(length)
modifiedColours = ShortArray(length)
repeat(length) { count ->
originalColours!![count] = buffer.readUnsignedShort().toShort()
modifiedColours!![count] = buffer.readUnsignedShort().toShort()
}
}
fun readTextures(buffer: Reader) {
val length = buffer.readUnsignedByte()
originalTextureColours = ShortArray(length)
modifiedTextureColours = ShortArray(length)
repeat(length) { count ->
originalTextureColours!![count] = buffer.readUnsignedShort().toShort()
modifiedTextureColours!![count] = buffer.readUnsignedShort().toShort()
}
}
}

View file

@ -0,0 +1,124 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
import cacheops.cache.definition.Extra
data class AnimationDefinition(
override var id: Int = -1,
var durations: IntArray? = null,
var primaryFrames: IntArray? = null,
var loopOffset: Int = -1,
var interleaveOrder: BooleanArray? = null,
var priority: Int = 5,
var leftHandItem: Int = -1,
var rightHandItem: Int = -1,
var maxLoops: Int = 99,
var animatingPrecedence: Int = -1,
var walkingPrecedence: Int = -1,
var replayMode: Int = 2,
var secondaryFrames: IntArray? = null,
var anIntArrayArray700: Array<IntArray?>? = null,
var aBoolean691: Boolean = false,
var tweened: Boolean = false,
var aBoolean699: Boolean = false,
var anIntArray701: IntArray? = null,
var anIntArray690: IntArray? = null,
var anIntArray692: IntArray? = null,
override var extras: Map<String, Any> = emptyMap()
) : Definition, Extra {
val time: Long
get() = (durations?.sum() ?: 0) * 20L
val clientTicks: Int
get() {
if (durations == null) {
return 0
}
var total = 0
for (i in 0 until durations!!.size - 3) {
total += durations!![i]
}
return total
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as AnimationDefinition
if (id != other.id) return false
if (durations != null) {
if (other.durations == null) return false
if (!durations!!.contentEquals(other.durations!!)) return false
} else if (other.durations != null) return false
if (primaryFrames != null) {
if (other.primaryFrames == null) return false
if (!primaryFrames!!.contentEquals(other.primaryFrames!!)) return false
} else if (other.primaryFrames != null) return false
if (loopOffset != other.loopOffset) return false
if (interleaveOrder != null) {
if (other.interleaveOrder == null) return false
if (!interleaveOrder!!.contentEquals(other.interleaveOrder!!)) return false
} else if (other.interleaveOrder != null) return false
if (priority != other.priority) return false
if (leftHandItem != other.leftHandItem) return false
if (rightHandItem != other.rightHandItem) return false
if (maxLoops != other.maxLoops) return false
if (animatingPrecedence != other.animatingPrecedence) return false
if (walkingPrecedence != other.walkingPrecedence) return false
if (replayMode != other.replayMode) return false
if (secondaryFrames != null) {
if (other.secondaryFrames == null) return false
if (!secondaryFrames!!.contentEquals(other.secondaryFrames!!)) return false
} else if (other.secondaryFrames != null) return false
if (anIntArrayArray700 != null) {
if (other.anIntArrayArray700 == null) return false
if (!anIntArrayArray700!!.contentDeepEquals(other.anIntArrayArray700!!)) return false
} else if (other.anIntArrayArray700 != null) return false
if (aBoolean691 != other.aBoolean691) return false
if (tweened != other.tweened) return false
if (aBoolean699 != other.aBoolean699) return false
if (anIntArray701 != null) {
if (other.anIntArray701 == null) return false
if (!anIntArray701!!.contentEquals(other.anIntArray701!!)) return false
} else if (other.anIntArray701 != null) return false
if (anIntArray690 != null) {
if (other.anIntArray690 == null) return false
if (!anIntArray690!!.contentEquals(other.anIntArray690!!)) return false
} else if (other.anIntArray690 != null) return false
if (anIntArray692 != null) {
if (other.anIntArray692 == null) return false
if (!anIntArray692!!.contentEquals(other.anIntArray692!!)) return false
} else if (other.anIntArray692 != null) return false
if (extras != other.extras) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + (durations?.contentHashCode() ?: 0)
result = 31 * result + (primaryFrames?.contentHashCode() ?: 0)
result = 31 * result + loopOffset
result = 31 * result + (interleaveOrder?.contentHashCode() ?: 0)
result = 31 * result + priority
result = 31 * result + leftHandItem
result = 31 * result + rightHandItem
result = 31 * result + maxLoops
result = 31 * result + animatingPrecedence
result = 31 * result + walkingPrecedence
result = 31 * result + replayMode
result = 31 * result + (secondaryFrames?.contentHashCode() ?: 0)
result = 31 * result + (anIntArrayArray700?.contentDeepHashCode() ?: 0)
result = 31 * result + aBoolean691.hashCode()
result = 31 * result + tweened.hashCode()
result = 31 * result + aBoolean699.hashCode()
result = 31 * result + (anIntArray701?.contentHashCode() ?: 0)
result = 31 * result + (anIntArray690?.contentHashCode() ?: 0)
result = 31 * result + (anIntArray692?.contentHashCode() ?: 0)
result = 31 * result + extras.hashCode()
return result
}
}

View file

@ -0,0 +1,16 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
/**
* Equipment Slots Definition
*/
@Suppress("ArrayInDataClass")
data class BodyDefinition(
override var id: Int = -1,
var disabledSlots: IntArray = IntArray(0),
var anInt4506: Int = -1,
var anInt4504: Int = -1,
var anIntArray4501: IntArray? = null,
var anIntArray4507: IntArray? = null
) : Definition

View file

@ -0,0 +1,71 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
data class ClientScriptDefinition(
override var id: Int = -1,
var intArgumentCount: Int = 0,
var stringVariableCount: Int = 0,
var longVariableCount: Int = 0,
var intVariableCount: Int = 0,
var stringArgumentCount: Int = 0,
var longArgumentCount: Int = 0,
var switchStatementIndices: Array<List<Pair<Int, Int>>>? = null,
var name: String? = null,
var instructions: IntArray = intArrayOf(),
var stringOperands: Array<String?>? = null,
var longOperands: LongArray? = null,
var intOperands: IntArray? = null
) : Definition {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ClientScriptDefinition
if (id != other.id) return false
if (intArgumentCount != other.intArgumentCount) return false
if (stringVariableCount != other.stringVariableCount) return false
if (longVariableCount != other.longVariableCount) return false
if (intVariableCount != other.intVariableCount) return false
if (stringArgumentCount != other.stringArgumentCount) return false
if (longArgumentCount != other.longArgumentCount) return false
if (switchStatementIndices != null) {
if (other.switchStatementIndices == null) return false
if (!switchStatementIndices!!.contentEquals(other.switchStatementIndices!!)) return false
} else if (other.switchStatementIndices != null) return false
if (name != other.name) return false
if (!instructions.contentEquals(other.instructions)) return false
if (stringOperands != null) {
if (other.stringOperands == null) return false
if (!stringOperands!!.contentEquals(other.stringOperands!!)) return false
} else if (other.stringOperands != null) return false
if (longOperands != null) {
if (other.longOperands == null) return false
if (!longOperands!!.contentEquals(other.longOperands!!)) return false
} else if (other.longOperands != null) return false
if (intOperands != null) {
if (other.intOperands == null) return false
if (!intOperands!!.contentEquals(other.intOperands!!)) return false
} else if (other.intOperands != null) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + intArgumentCount
result = 31 * result + stringVariableCount
result = 31 * result + longVariableCount
result = 31 * result + intVariableCount
result = 31 * result + stringArgumentCount
result = 31 * result + longArgumentCount
result = 31 * result + (switchStatementIndices?.contentHashCode() ?: 0)
result = 31 * result + (name?.hashCode() ?: 0)
result = 31 * result + instructions.contentHashCode()
result = 31 * result + (stringOperands?.contentHashCode() ?: 0)
result = 31 * result + (longOperands?.contentHashCode() ?: 0)
result = 31 * result + (intOperands?.contentHashCode() ?: 0)
return result
}
}

View file

@ -0,0 +1,19 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
data class EnumDefinition(
override var id: Int = -1,
var keyType: Char = 0.toChar(),
var valueType: Char = 0.toChar(),
var defaultString: String = "null",
var defaultInt: Int = 0,
var length: Int = 0,
var map: HashMap<Int, Any>? = null
) : Definition {
fun getKey(value: Any) = map?.filterValues { it == value }?.keys?.firstOrNull() ?: -1
fun getInt(id: Int) = map?.get(id) as? Int ?: defaultInt
fun getString(id: Int) = map?.get(id) as? String ?: defaultString
}

View file

@ -0,0 +1,82 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
import cacheops.cache.definition.Extra
import cacheops.cache.definition.Recolourable
data class GraphicDefinition(
override var id: Int = -1,
var modelId: Int = 0,
var animationId: Int = -1,
var sizeXY: Int = 128,
var sizeZ: Int = 128,
var rotation: Int = 0,
var ambience: Int = 0,
var contrast: Int = 0,
var aByte2381: Byte = 0,
var anInt2385: Int = -1,
var aBoolean2402: Boolean = false,
override var originalColours: ShortArray? = null,
override var modifiedColours: ShortArray? = null,
override var originalTextureColours: ShortArray? = null,
override var modifiedTextureColours: ShortArray? = null,
override var extras: Map<String, Any> = emptyMap()
) : Definition, Recolourable, Extra {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as GraphicDefinition
if (id != other.id) return false
if (modelId != other.modelId) return false
if (animationId != other.animationId) return false
if (sizeXY != other.sizeXY) return false
if (sizeZ != other.sizeZ) return false
if (rotation != other.rotation) return false
if (ambience != other.ambience) return false
if (contrast != other.contrast) return false
if (aByte2381 != other.aByte2381) return false
if (anInt2385 != other.anInt2385) return false
if (aBoolean2402 != other.aBoolean2402) return false
if (originalColours != null) {
if (other.originalColours == null) return false
if (!originalColours!!.contentEquals(other.originalColours!!)) return false
} else if (other.originalColours != null) return false
if (modifiedColours != null) {
if (other.modifiedColours == null) return false
if (!modifiedColours!!.contentEquals(other.modifiedColours!!)) return false
} else if (other.modifiedColours != null) return false
if (originalTextureColours != null) {
if (other.originalTextureColours == null) return false
if (!originalTextureColours!!.contentEquals(other.originalTextureColours!!)) return false
} else if (other.originalTextureColours != null) return false
if (modifiedTextureColours != null) {
if (other.modifiedTextureColours == null) return false
if (!modifiedTextureColours!!.contentEquals(other.modifiedTextureColours!!)) return false
} else if (other.modifiedTextureColours != null) return false
if (extras != other.extras) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + modelId
result = 31 * result + animationId
result = 31 * result + sizeXY
result = 31 * result + sizeZ
result = 31 * result + rotation
result = 31 * result + ambience
result = 31 * result + contrast
result = 31 * result + aByte2381
result = 31 * result + anInt2385
result = 31 * result + aBoolean2402.hashCode()
result = 31 * result + (originalColours?.contentHashCode() ?: 0)
result = 31 * result + (modifiedColours?.contentHashCode() ?: 0)
result = 31 * result + (originalTextureColours?.contentHashCode() ?: 0)
result = 31 * result + (modifiedTextureColours?.contentHashCode() ?: 0)
result = 31 * result + extras.hashCode()
return result
}
}

View file

@ -0,0 +1,36 @@
package cacheops.cache.definition.data
import java.awt.image.BufferedImage
@Suppress("ArrayInDataClass")
data class IndexedSprite(
var offsetX: Int = 0,
var offsetY: Int = 0,
var width: Int = 0,
var height: Int = 0,
var deltaHeight: Int = 0,
var deltaWidth: Int = 0,
var alpha: ByteArray? = null
) {
lateinit var raster: ByteArray
lateinit var palette: IntArray
fun toBufferedImage(): BufferedImage {
val bi = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
for (x in 0 until width) {
for (y in 0 until height) {
val i = x + y * width
if (alpha == null) {
val colour = palette[raster[i].toInt() and 255]
if (colour != 0) {
bi.setRGB(x, y, -16777216 or colour)
}
} else {
bi.setRGB(x, y, palette[raster[i].toInt() and 255] or (alpha!![i].toInt() shl 24))
}
}
}
return bi
}
}

View file

@ -0,0 +1,10 @@
package cacheops.cache.definition.data
object Instructions {
const val PUSH_INT = 0
const val PUSH_STRING = 3
const val MERGE_STRINGS = 37
const val CALL_CS2 = 40
const val SWITCH = 51
const val GOTO = 6
}

View file

@ -0,0 +1,409 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
import cacheops.cache.definition.Extra
data class InterfaceComponentDefinition(
override var id: Int = -1,
var type: Int = 0,
var unknown: String? = null,
var contentType: Int = 0,
var basePositionX: Int = 0,
var basePositionY: Int = 0,
var baseWidth: Int = 0,
var baseHeight: Int = 0,
var horizontalSizeMode: Byte = 0,
var verticalSizeMode: Byte = 0,
var horizontalPositionMode: Byte = 0,
var verticalPositionMode: Byte = 0,
var parent: Int = -1,
var hidden: Boolean = false,
var disableHover: Boolean = false,
var scrollWidth: Int = 0,
var scrollHeight: Int = 0,
var colour: Int = 0,
var filled: Boolean = false,
var alpha: Int = 0,
var fontId: Int = -1,
var monochrome: Boolean = true,
var text: String = "",
var lineHeight: Int = 0,
var horizontalTextAlign: Int = 0,
var verticalTextAlign: Int = 0,
var shaded: Boolean = false,
var lineCount: Int = 0,
var defaultImage: Int = -1,
var imageRotation: Int = 0,
var aBoolean4861: Boolean = false,
var imageRepeat: Boolean = false,
var rotation: Int = 0,
var backgroundColour: Int = 0,
var flipVertical: Boolean = false,
var flipHorizontal: Boolean = false,
var aBoolean4782: Boolean = true,
var defaultMediaType: Int = 1,
var defaultMediaId: Int = 0,
var animated: Boolean = false,
var centreType: Boolean = false,
var ignoreZBuffer: Boolean = false,
var viewportX: Int = 0,
var viewportY: Int = 0,
var viewportZ: Int = 0,
var spritePitch: Int = 0,
var spriteRoll: Int = 0,
var spriteYaw: Int = 0,
var spriteScale: Int = 100,
var animation: Int = -1,
var viewportWidth: Int = 0,
var viewportHeight: Int = 0,
var lineWidth: Int = 1,
var lineMirrored: Boolean = false,
var keyRepeat: ByteArray? = null,
var keyCodes: ByteArray? = null,
var keyModifiers: IntArray? = null,
var clickable: Boolean = false,
var name: String = "",
var options: Array<String>? = null,
var mouseIcon: IntArray? = null,
var optionOverride: String? = null,
var anInt4708: Int = 0,// Drag type
var anInt4795: Int = 0,// Drag slider?
var anInt4860: Int = 0,// Friends list icons/buttons?
var useOption: String = "",
var anInt4698: Int = -1,
var anInt4839: Int = -1,// Unused
var anInt4761: Int = -1,// Unused
var setting: InterfaceComponentSetting = InterfaceComponentSetting(0, -1),
val params: HashMap<Long, Any>? = null,
var anObjectArray4758: Array<Any>? = null,
var mouseEnterHandler: Array<Any>? = null,
var mouseExitHandler: Array<Any>? = null,
var anObjectArray4771: Array<Any>? = null,
var anObjectArray4768: Array<Any>? = null,
var stateChangeHandler: Array<Any>? = null,
var invUpdateHandler: Array<Any>? = null,
var refreshHandler: Array<Any>? = null,
var updateHandler: Array<Any>? = null,
var anObjectArray4770: Array<Any>? = null,
var anObjectArray4751: Array<Any>? = null,
var mouseMotionHandler: Array<Any>? = null,
var mousePressedHandler: Array<Any>? = null,
var mouseDraggedHandler: Array<Any>? = null,
var mouseReleasedHandler: Array<Any>? = null,
var mouseDragPassHandler: Array<Any>? = null,
var anObjectArray4852: Array<Any>? = null,
var anObjectArray4711: Array<Any>? = null,
var anObjectArray4753: Array<Any>? = null,
var anObjectArray4688: Array<Any>? = null,
var anObjectArray4775: Array<Any>? = null,
var clientVarp: IntArray? = null,
var containers: IntArray? = null,
var anIntArray4789: IntArray? = null,
var clientVarc: IntArray? = null,
var anIntArray4805: IntArray? = null,
var hasScript: Boolean = false,
override var extras: Map<String, Any> = emptyMap()
) : Definition, Extra {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as InterfaceComponentDefinition
if (id != other.id) return false
if (type != other.type) return false
if (unknown != other.unknown) return false
if (contentType != other.contentType) return false
if (basePositionX != other.basePositionX) return false
if (basePositionY != other.basePositionY) return false
if (baseWidth != other.baseWidth) return false
if (baseHeight != other.baseHeight) return false
if (horizontalSizeMode != other.horizontalSizeMode) return false
if (verticalSizeMode != other.verticalSizeMode) return false
if (horizontalPositionMode != other.horizontalPositionMode) return false
if (verticalPositionMode != other.verticalPositionMode) return false
if (parent != other.parent) return false
if (hidden != other.hidden) return false
if (disableHover != other.disableHover) return false
if (scrollWidth != other.scrollWidth) return false
if (scrollHeight != other.scrollHeight) return false
if (colour != other.colour) return false
if (filled != other.filled) return false
if (alpha != other.alpha) return false
if (fontId != other.fontId) return false
if (monochrome != other.monochrome) return false
if (text != other.text) return false
if (lineHeight != other.lineHeight) return false
if (horizontalTextAlign != other.horizontalTextAlign) return false
if (verticalTextAlign != other.verticalTextAlign) return false
if (shaded != other.shaded) return false
if (lineCount != other.lineCount) return false
if (defaultImage != other.defaultImage) return false
if (imageRotation != other.imageRotation) return false
if (aBoolean4861 != other.aBoolean4861) return false
if (imageRepeat != other.imageRepeat) return false
if (rotation != other.rotation) return false
if (backgroundColour != other.backgroundColour) return false
if (flipVertical != other.flipVertical) return false
if (flipHorizontal != other.flipHorizontal) return false
if (aBoolean4782 != other.aBoolean4782) return false
if (defaultMediaType != other.defaultMediaType) return false
if (defaultMediaId != other.defaultMediaId) return false
if (animated != other.animated) return false
if (centreType != other.centreType) return false
if (ignoreZBuffer != other.ignoreZBuffer) return false
if (viewportX != other.viewportX) return false
if (viewportY != other.viewportY) return false
if (viewportZ != other.viewportZ) return false
if (spritePitch != other.spritePitch) return false
if (spriteRoll != other.spriteRoll) return false
if (spriteYaw != other.spriteYaw) return false
if (spriteScale != other.spriteScale) return false
if (animation != other.animation) return false
if (viewportWidth != other.viewportWidth) return false
if (viewportHeight != other.viewportHeight) return false
if (lineWidth != other.lineWidth) return false
if (lineMirrored != other.lineMirrored) return false
if (keyRepeat != null) {
if (other.keyRepeat == null) return false
if (!keyRepeat!!.contentEquals(other.keyRepeat!!)) return false
} else if (other.keyRepeat != null) return false
if (keyCodes != null) {
if (other.keyCodes == null) return false
if (!keyCodes!!.contentEquals(other.keyCodes!!)) return false
} else if (other.keyCodes != null) return false
if (keyModifiers != null) {
if (other.keyModifiers == null) return false
if (!keyModifiers!!.contentEquals(other.keyModifiers!!)) return false
} else if (other.keyModifiers != null) return false
if (clickable != other.clickable) return false
if (name != other.name) return false
if (options != null) {
if (other.options == null) return false
if (!options!!.contentEquals(other.options!!)) return false
} else if (other.options != null) return false
if (mouseIcon != null) {
if (other.mouseIcon == null) return false
if (!mouseIcon!!.contentEquals(other.mouseIcon!!)) return false
} else if (other.mouseIcon != null) return false
if (optionOverride != other.optionOverride) return false
if (anInt4708 != other.anInt4708) return false
if (anInt4795 != other.anInt4795) return false
if (anInt4860 != other.anInt4860) return false
if (useOption != other.useOption) return false
if (anInt4698 != other.anInt4698) return false
if (anInt4839 != other.anInt4839) return false
if (anInt4761 != other.anInt4761) return false
if (setting != other.setting) return false
if (params != other.params) return false
if (anObjectArray4758 != null) {
if (other.anObjectArray4758 == null) return false
if (!anObjectArray4758!!.contentEquals(other.anObjectArray4758!!)) return false
} else if (other.anObjectArray4758 != null) return false
if (mouseEnterHandler != null) {
if (other.mouseEnterHandler == null) return false
if (!mouseEnterHandler!!.contentEquals(other.mouseEnterHandler!!)) return false
} else if (other.mouseEnterHandler != null) return false
if (mouseExitHandler != null) {
if (other.mouseExitHandler == null) return false
if (!mouseExitHandler!!.contentEquals(other.mouseExitHandler!!)) return false
} else if (other.mouseExitHandler != null) return false
if (anObjectArray4771 != null) {
if (other.anObjectArray4771 == null) return false
if (!anObjectArray4771!!.contentEquals(other.anObjectArray4771!!)) return false
} else if (other.anObjectArray4771 != null) return false
if (anObjectArray4768 != null) {
if (other.anObjectArray4768 == null) return false
if (!anObjectArray4768!!.contentEquals(other.anObjectArray4768!!)) return false
} else if (other.anObjectArray4768 != null) return false
if (stateChangeHandler != null) {
if (other.stateChangeHandler == null) return false
if (!stateChangeHandler!!.contentEquals(other.stateChangeHandler!!)) return false
} else if (other.stateChangeHandler != null) return false
if (invUpdateHandler != null) {
if (other.invUpdateHandler == null) return false
if (!invUpdateHandler!!.contentEquals(other.invUpdateHandler!!)) return false
} else if (other.invUpdateHandler != null) return false
if (refreshHandler != null) {
if (other.refreshHandler == null) return false
if (!refreshHandler!!.contentEquals(other.refreshHandler!!)) return false
} else if (other.refreshHandler != null) return false
if (updateHandler != null) {
if (other.updateHandler == null) return false
if (!updateHandler!!.contentEquals(other.updateHandler!!)) return false
} else if (other.updateHandler != null) return false
if (anObjectArray4770 != null) {
if (other.anObjectArray4770 == null) return false
if (!anObjectArray4770!!.contentEquals(other.anObjectArray4770!!)) return false
} else if (other.anObjectArray4770 != null) return false
if (anObjectArray4751 != null) {
if (other.anObjectArray4751 == null) return false
if (!anObjectArray4751!!.contentEquals(other.anObjectArray4751!!)) return false
} else if (other.anObjectArray4751 != null) return false
if (mouseMotionHandler != null) {
if (other.mouseMotionHandler == null) return false
if (!mouseMotionHandler!!.contentEquals(other.mouseMotionHandler!!)) return false
} else if (other.mouseMotionHandler != null) return false
if (mousePressedHandler != null) {
if (other.mousePressedHandler == null) return false
if (!mousePressedHandler!!.contentEquals(other.mousePressedHandler!!)) return false
} else if (other.mousePressedHandler != null) return false
if (mouseDraggedHandler != null) {
if (other.mouseDraggedHandler == null) return false
if (!mouseDraggedHandler!!.contentEquals(other.mouseDraggedHandler!!)) return false
} else if (other.mouseDraggedHandler != null) return false
if (mouseReleasedHandler != null) {
if (other.mouseReleasedHandler == null) return false
if (!mouseReleasedHandler!!.contentEquals(other.mouseReleasedHandler!!)) return false
} else if (other.mouseReleasedHandler != null) return false
if (mouseDragPassHandler != null) {
if (other.mouseDragPassHandler == null) return false
if (!mouseDragPassHandler!!.contentEquals(other.mouseDragPassHandler!!)) return false
} else if (other.mouseDragPassHandler != null) return false
if (anObjectArray4852 != null) {
if (other.anObjectArray4852 == null) return false
if (!anObjectArray4852!!.contentEquals(other.anObjectArray4852!!)) return false
} else if (other.anObjectArray4852 != null) return false
if (anObjectArray4711 != null) {
if (other.anObjectArray4711 == null) return false
if (!anObjectArray4711!!.contentEquals(other.anObjectArray4711!!)) return false
} else if (other.anObjectArray4711 != null) return false
if (anObjectArray4753 != null) {
if (other.anObjectArray4753 == null) return false
if (!anObjectArray4753!!.contentEquals(other.anObjectArray4753!!)) return false
} else if (other.anObjectArray4753 != null) return false
if (anObjectArray4688 != null) {
if (other.anObjectArray4688 == null) return false
if (!anObjectArray4688!!.contentEquals(other.anObjectArray4688!!)) return false
} else if (other.anObjectArray4688 != null) return false
if (anObjectArray4775 != null) {
if (other.anObjectArray4775 == null) return false
if (!anObjectArray4775!!.contentEquals(other.anObjectArray4775!!)) return false
} else if (other.anObjectArray4775 != null) return false
if (clientVarp != null) {
if (other.clientVarp == null) return false
if (!clientVarp!!.contentEquals(other.clientVarp!!)) return false
} else if (other.clientVarp != null) return false
if (containers != null) {
if (other.containers == null) return false
if (!containers!!.contentEquals(other.containers!!)) return false
} else if (other.containers != null) return false
if (anIntArray4789 != null) {
if (other.anIntArray4789 == null) return false
if (!anIntArray4789!!.contentEquals(other.anIntArray4789!!)) return false
} else if (other.anIntArray4789 != null) return false
if (clientVarc != null) {
if (other.clientVarc == null) return false
if (!clientVarc!!.contentEquals(other.clientVarc!!)) return false
} else if (other.clientVarc != null) return false
if (anIntArray4805 != null) {
if (other.anIntArray4805 == null) return false
if (!anIntArray4805!!.contentEquals(other.anIntArray4805!!)) return false
} else if (other.anIntArray4805 != null) return false
if (hasScript != other.hasScript) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + type
result = 31 * result + (unknown?.hashCode() ?: 0)
result = 31 * result + contentType
result = 31 * result + basePositionX
result = 31 * result + basePositionY
result = 31 * result + baseWidth
result = 31 * result + baseHeight
result = 31 * result + horizontalSizeMode
result = 31 * result + verticalSizeMode
result = 31 * result + horizontalPositionMode
result = 31 * result + verticalPositionMode
result = 31 * result + parent
result = 31 * result + hidden.hashCode()
result = 31 * result + disableHover.hashCode()
result = 31 * result + scrollWidth
result = 31 * result + scrollHeight
result = 31 * result + colour
result = 31 * result + filled.hashCode()
result = 31 * result + alpha
result = 31 * result + fontId
result = 31 * result + monochrome.hashCode()
result = 31 * result + text.hashCode()
result = 31 * result + lineHeight
result = 31 * result + horizontalTextAlign
result = 31 * result + verticalTextAlign
result = 31 * result + shaded.hashCode()
result = 31 * result + lineCount
result = 31 * result + defaultImage
result = 31 * result + imageRotation
result = 31 * result + aBoolean4861.hashCode()
result = 31 * result + imageRepeat.hashCode()
result = 31 * result + rotation
result = 31 * result + backgroundColour
result = 31 * result + flipVertical.hashCode()
result = 31 * result + flipHorizontal.hashCode()
result = 31 * result + aBoolean4782.hashCode()
result = 31 * result + defaultMediaType
result = 31 * result + defaultMediaId
result = 31 * result + animated.hashCode()
result = 31 * result + centreType.hashCode()
result = 31 * result + ignoreZBuffer.hashCode()
result = 31 * result + viewportX
result = 31 * result + viewportY
result = 31 * result + viewportZ
result = 31 * result + spritePitch
result = 31 * result + spriteRoll
result = 31 * result + spriteYaw
result = 31 * result + spriteScale
result = 31 * result + animation
result = 31 * result + viewportWidth
result = 31 * result + viewportHeight
result = 31 * result + lineWidth
result = 31 * result + lineMirrored.hashCode()
result = 31 * result + (keyRepeat?.contentHashCode() ?: 0)
result = 31 * result + (keyCodes?.contentHashCode() ?: 0)
result = 31 * result + (keyModifiers?.contentHashCode() ?: 0)
result = 31 * result + clickable.hashCode()
result = 31 * result + name.hashCode()
result = 31 * result + (options?.contentHashCode() ?: 0)
result = 31 * result + (mouseIcon?.contentHashCode() ?: 0)
result = 31 * result + (optionOverride?.hashCode() ?: 0)
result = 31 * result + anInt4708
result = 31 * result + anInt4795
result = 31 * result + anInt4860
result = 31 * result + useOption.hashCode()
result = 31 * result + anInt4698
result = 31 * result + anInt4839
result = 31 * result + anInt4761
result = 31 * result + setting.hashCode()
result = 31 * result + (params?.hashCode() ?: 0)
result = 31 * result + (anObjectArray4758?.contentHashCode() ?: 0)
result = 31 * result + (mouseEnterHandler?.contentHashCode() ?: 0)
result = 31 * result + (mouseExitHandler?.contentHashCode() ?: 0)
result = 31 * result + (anObjectArray4771?.contentHashCode() ?: 0)
result = 31 * result + (anObjectArray4768?.contentHashCode() ?: 0)
result = 31 * result + (stateChangeHandler?.contentHashCode() ?: 0)
result = 31 * result + (invUpdateHandler?.contentHashCode() ?: 0)
result = 31 * result + (refreshHandler?.contentHashCode() ?: 0)
result = 31 * result + (updateHandler?.contentHashCode() ?: 0)
result = 31 * result + (anObjectArray4770?.contentHashCode() ?: 0)
result = 31 * result + (anObjectArray4751?.contentHashCode() ?: 0)
result = 31 * result + (mouseMotionHandler?.contentHashCode() ?: 0)
result = 31 * result + (mousePressedHandler?.contentHashCode() ?: 0)
result = 31 * result + (mouseDraggedHandler?.contentHashCode() ?: 0)
result = 31 * result + (mouseReleasedHandler?.contentHashCode() ?: 0)
result = 31 * result + (mouseDragPassHandler?.contentHashCode() ?: 0)
result = 31 * result + (anObjectArray4852?.contentHashCode() ?: 0)
result = 31 * result + (anObjectArray4711?.contentHashCode() ?: 0)
result = 31 * result + (anObjectArray4753?.contentHashCode() ?: 0)
result = 31 * result + (anObjectArray4688?.contentHashCode() ?: 0)
result = 31 * result + (anObjectArray4775?.contentHashCode() ?: 0)
result = 31 * result + (clientVarp?.contentHashCode() ?: 0)
result = 31 * result + (containers?.contentHashCode() ?: 0)
result = 31 * result + (anIntArray4789?.contentHashCode() ?: 0)
result = 31 * result + (clientVarc?.contentHashCode() ?: 0)
result = 31 * result + (anIntArray4805?.contentHashCode() ?: 0)
result = 31 * result + hasScript.hashCode()
return result
}
}

View file

@ -0,0 +1,27 @@
package cacheops.cache.definition.data
data class InterfaceComponentSetting(var setting: Int, var anInt7413: Int) {
fun method2743(): Int {
return setting and 0x3fda8 shr 11
}
fun method2744(): Boolean {
return 0x1 and setting shr 22 != 0
}
fun method2745(): Int {
return 0x1d36c1 and setting shr 18
}
fun method2746(): Boolean {
return 0x1 and setting != 0
}
fun method2747(): Boolean {
return 0x1 and setting shr 21 != 0
}
fun unlockedSlot(slot: Int): Boolean {
return 0x1 and setting shr slot + 1 != 0
}
}

View file

@ -0,0 +1,11 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
import cacheops.cache.definition.Extra
@Suppress("ArrayInDataClass")
data class InterfaceDefinition(
override var id: Int = -1,
var components: Map<Int, InterfaceComponentDefinition>? = null,
override var extras: Map<String, Any> = emptyMap()
) : Definition, Extra

View file

@ -0,0 +1,249 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
import cacheops.cache.definition.ColorPalette
import cacheops.cache.definition.Extra
import cacheops.cache.definition.Parameterized
import cacheops.cache.definition.Recolourable
data class ItemDefinition(
override var id: Int = -1,
var modelId: Int = 0,
var name: String = "null",
var spriteScale: Int = 2000,
var spritePitch: Int = 0,
var spriteCameraRoll: Int = 0,
var spriteTranslateX: Int = 0,
var spriteTranslateY: Int = 0,
var stackable: Int = 0,
var cost: Int = 1,
var members: Boolean = false,
var multiStackSize: Int = -1,
var primaryMaleModel: Int = -1,
var secondaryMaleModel: Int = -1,
var primaryFemaleModel: Int = -1,
var secondaryFemaleModel: Int = -1,
var floorOptions: Array<String?> = arrayOf(null, null, "Take", null, null, "Examine"),
var options: Array<String?> = arrayOf(null, null, null, null, "Drop"),
override var originalColours: ShortArray? = null,
override var modifiedColours: ShortArray? = null,
override var originalTextureColours: ShortArray? = null,
override var modifiedTextureColours: ShortArray? = null,
override var recolourPalette: ByteArray? = null,
var exchangeable: Boolean = false,
var tertiaryMaleModel: Int = -1,
var tertiaryFemaleModel: Int = -1,
var primaryMaleDialogueHead: Int = -1,
var primaryFemaleDialogueHead: Int = -1,
var secondaryMaleDialogueHead: Int = -1,
var secondaryFemaleDialogueHead: Int = -1,
var spriteCameraYaw: Int = 0,
var dummyItem: Int = 0,
var noteId: Int = -1,
var notedTemplateId: Int = -1,
var stackIds: IntArray? = null,
var stackAmounts: IntArray? = null,
var floorScaleX: Int = 128,
var floorScaleZ: Int = 128,
var floorScaleY: Int = 128,
var ambience: Int = 0,
var diffusion: Int = 0,
var team: Int = 0,
var lendId: Int = -1,
var lendTemplateId: Int = -1,
var maleWieldX: Int = 0,
var maleWieldZ: Int = 0,
var maleWieldY: Int = 0,
var femaleWieldX: Int = 0,
var femaleWieldZ: Int = 0,
var femaleWieldY: Int = 0,
var primaryCursorOpcode: Int = -1,
var primaryCursor: Int = -1,
var secondaryCursorOpcode: Int = -1,
var secondaryCursor: Int = -1,
var primaryInterfaceCursorOpcode: Int = -1,
var primaryInterfaceCursor: Int = -1,
var secondaryInterfaceCursorOpcode: Int = -1,
var secondaryInterfaceCursor: Int = -1,
var campaigns: IntArray? = null,
var pickSizeShift: Int = 0,
var singleNoteId: Int = -1,
var singleNoteTemplateId: Int = -1,
override var params: HashMap<Long, Any>? = null,
override var extras: Map<String, Any> = emptyMap()
) : Definition, Recolourable, ColorPalette, Parameterized, Extra {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ItemDefinition
if (id != other.id) return false
if (modelId != other.modelId) return false
if (name != other.name) return false
if (spriteScale != other.spriteScale) return false
if (spritePitch != other.spritePitch) return false
if (spriteCameraRoll != other.spriteCameraRoll) return false
if (spriteTranslateX != other.spriteTranslateX) return false
if (spriteTranslateY != other.spriteTranslateY) return false
if (stackable != other.stackable) return false
if (cost != other.cost) return false
if (members != other.members) return false
if (multiStackSize != other.multiStackSize) return false
if (primaryMaleModel != other.primaryMaleModel) return false
if (secondaryMaleModel != other.secondaryMaleModel) return false
if (primaryFemaleModel != other.primaryFemaleModel) return false
if (secondaryFemaleModel != other.secondaryFemaleModel) return false
if (!floorOptions.contentEquals(other.floorOptions)) return false
if (!options.contentEquals(other.options)) return false
if (originalColours != null) {
if (other.originalColours == null) return false
if (!originalColours!!.contentEquals(other.originalColours!!)) return false
} else if (other.originalColours != null) return false
if (modifiedColours != null) {
if (other.modifiedColours == null) return false
if (!modifiedColours!!.contentEquals(other.modifiedColours!!)) return false
} else if (other.modifiedColours != null) return false
if (originalTextureColours != null) {
if (other.originalTextureColours == null) return false
if (!originalTextureColours!!.contentEquals(other.originalTextureColours!!)) return false
} else if (other.originalTextureColours != null) return false
if (modifiedTextureColours != null) {
if (other.modifiedTextureColours == null) return false
if (!modifiedTextureColours!!.contentEquals(other.modifiedTextureColours!!)) return false
} else if (other.modifiedTextureColours != null) return false
if (recolourPalette != null) {
if (other.recolourPalette == null) return false
if (!recolourPalette!!.contentEquals(other.recolourPalette!!)) return false
} else if (other.recolourPalette != null) return false
if (exchangeable != other.exchangeable) return false
if (tertiaryMaleModel != other.tertiaryMaleModel) return false
if (tertiaryFemaleModel != other.tertiaryFemaleModel) return false
if (primaryMaleDialogueHead != other.primaryMaleDialogueHead) return false
if (primaryFemaleDialogueHead != other.primaryFemaleDialogueHead) return false
if (secondaryMaleDialogueHead != other.secondaryMaleDialogueHead) return false
if (secondaryFemaleDialogueHead != other.secondaryFemaleDialogueHead) return false
if (spriteCameraYaw != other.spriteCameraYaw) return false
if (dummyItem != other.dummyItem) return false
if (noteId != other.noteId) return false
if (notedTemplateId != other.notedTemplateId) return false
if (stackIds != null) {
if (other.stackIds == null) return false
if (!stackIds!!.contentEquals(other.stackIds!!)) return false
} else if (other.stackIds != null) return false
if (stackAmounts != null) {
if (other.stackAmounts == null) return false
if (!stackAmounts!!.contentEquals(other.stackAmounts!!)) return false
} else if (other.stackAmounts != null) return false
if (floorScaleX != other.floorScaleX) return false
if (floorScaleZ != other.floorScaleZ) return false
if (floorScaleY != other.floorScaleY) return false
if (ambience != other.ambience) return false
if (diffusion != other.diffusion) return false
if (team != other.team) return false
if (lendId != other.lendId) return false
if (lendTemplateId != other.lendTemplateId) return false
if (maleWieldX != other.maleWieldX) return false
if (maleWieldZ != other.maleWieldZ) return false
if (maleWieldY != other.maleWieldY) return false
if (femaleWieldX != other.femaleWieldX) return false
if (femaleWieldZ != other.femaleWieldZ) return false
if (femaleWieldY != other.femaleWieldY) return false
if (primaryCursorOpcode != other.primaryCursorOpcode) return false
if (primaryCursor != other.primaryCursor) return false
if (secondaryCursorOpcode != other.secondaryCursorOpcode) return false
if (secondaryCursor != other.secondaryCursor) return false
if (primaryInterfaceCursorOpcode != other.primaryInterfaceCursorOpcode) return false
if (primaryInterfaceCursor != other.primaryInterfaceCursor) return false
if (secondaryInterfaceCursorOpcode != other.secondaryInterfaceCursorOpcode) return false
if (secondaryInterfaceCursor != other.secondaryInterfaceCursor) return false
if (campaigns != null) {
if (other.campaigns == null) return false
if (!campaigns!!.contentEquals(other.campaigns!!)) return false
} else if (other.campaigns != null) return false
if (pickSizeShift != other.pickSizeShift) return false
if (singleNoteId != other.singleNoteId) return false
if (singleNoteTemplateId != other.singleNoteTemplateId) return false
if (params != other.params) return false
if (extras != other.extras) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + modelId
result = 31 * result + name.hashCode()
result = 31 * result + spriteScale
result = 31 * result + spritePitch
result = 31 * result + spriteCameraRoll
result = 31 * result + spriteTranslateX
result = 31 * result + spriteTranslateY
result = 31 * result + stackable
result = 31 * result + cost
result = 31 * result + members.hashCode()
result = 31 * result + multiStackSize
result = 31 * result + primaryMaleModel
result = 31 * result + secondaryMaleModel
result = 31 * result + primaryFemaleModel
result = 31 * result + secondaryFemaleModel
result = 31 * result + floorOptions.contentHashCode()
result = 31 * result + options.contentHashCode()
result = 31 * result + (originalColours?.contentHashCode() ?: 0)
result = 31 * result + (modifiedColours?.contentHashCode() ?: 0)
result = 31 * result + (originalTextureColours?.contentHashCode() ?: 0)
result = 31 * result + (modifiedTextureColours?.contentHashCode() ?: 0)
result = 31 * result + (recolourPalette?.contentHashCode() ?: 0)
result = 31 * result + exchangeable.hashCode()
result = 31 * result + tertiaryMaleModel
result = 31 * result + tertiaryFemaleModel
result = 31 * result + primaryMaleDialogueHead
result = 31 * result + primaryFemaleDialogueHead
result = 31 * result + secondaryMaleDialogueHead
result = 31 * result + secondaryFemaleDialogueHead
result = 31 * result + spriteCameraYaw
result = 31 * result + dummyItem
result = 31 * result + noteId
result = 31 * result + notedTemplateId
result = 31 * result + (stackIds?.contentHashCode() ?: 0)
result = 31 * result + (stackAmounts?.contentHashCode() ?: 0)
result = 31 * result + floorScaleX
result = 31 * result + floorScaleZ
result = 31 * result + floorScaleY
result = 31 * result + ambience
result = 31 * result + diffusion
result = 31 * result + team
result = 31 * result + lendId
result = 31 * result + lendTemplateId
result = 31 * result + maleWieldX
result = 31 * result + maleWieldZ
result = 31 * result + maleWieldY
result = 31 * result + femaleWieldX
result = 31 * result + femaleWieldZ
result = 31 * result + femaleWieldY
result = 31 * result + primaryCursorOpcode
result = 31 * result + primaryCursor
result = 31 * result + secondaryCursorOpcode
result = 31 * result + secondaryCursor
result = 31 * result + primaryInterfaceCursorOpcode
result = 31 * result + primaryInterfaceCursor
result = 31 * result + secondaryInterfaceCursorOpcode
result = 31 * result + secondaryInterfaceCursor
result = 31 * result + (campaigns?.contentHashCode() ?: 0)
result = 31 * result + pickSizeShift
result = 31 * result + singleNoteId
result = 31 * result + singleNoteTemplateId
result = 31 * result + (params?.hashCode() ?: 0)
result = 31 * result + extras.hashCode()
return result
}
val noted: Boolean
get() = notedTemplateId != -1
val lent: Boolean
get() = lendTemplateId != -1
val singleNote: Boolean
get() = singleNoteTemplateId != -1
}

View file

@ -0,0 +1,24 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
data class MapDefinition(
override var id: Int = -1,
val tiles: MutableMap<Int, MapTile> = mutableMapOf(),
val objects: MutableList<MapObject> = mutableListOf()
) : Definition {
fun getTile(localX: Int, localY: Int, plane: Int) = tiles[getHash(localX, localY, plane)] ?: MapTile.EMPTY
fun setTile(localX: Int, localY: Int, plane: Int, tile: MapTile) {
tiles[getHash(localX, localY, plane)] = tile
}
companion object {
fun getHash(localX: Int, localY: Int, plane: Int): Int {
return localY + (localX shl 6) + (plane shl 12)
}
fun getLocalX(tile: Int) = tile shr 6 and 0x3f
fun getLocalY(tile: Int) = tile and 0x3f
fun getPlane(tile: Int) = tile shr 12 and 0x3
}
}

View file

@ -0,0 +1,43 @@
package cacheops.cache.definition.data
inline class MapObject(val hash: Long) {
constructor(id: Int, x: Int, y: Int, plane: Int, type: Int, rotation: Int) : this(getHash(id, x, y, plane, type, rotation))
val id: Int
get() = getId(hash)
val x: Int
get() = getX(hash)
val y: Int
get() = getY(hash)
val plane: Int
get() = getPlane(hash)
val type: Int
get() = getType(hash)
val rotation: Int
get() = getRotation(hash)
companion object {
fun getHash(id: Int, x: Int, y: Int, plane: Int, type: Int, rotation: Int): Long {
return getHash(id.toLong(), x.toLong(), y.toLong(), plane.toLong(), type.toLong(), rotation.toLong())
}
fun getHash(id: Long, x: Long, y: Long, plane: Long, type: Long, rotation: Long): Long {
return rotation + (type shl 2) + (plane shl 7) + (y shl 9) + (x shl 23) + (id shl 37)
}
fun getId(hash: Long): Int = (hash shr 37 and 0x1ffff).toInt()
fun getX(hash: Long): Int = (hash shr 23 and 0x3fff).toInt()
fun getY(hash: Long): Int = (hash shr 9 and 0x3fff).toInt()
fun getPlane(hash: Long): Int = (hash shr 7 and 0x3).toInt()
fun getType(hash: Long): Int = (hash shr 2 and 0x1f).toInt()
fun getRotation(hash: Long): Int = (hash and 0x3).toInt()
}
}

View file

@ -0,0 +1,58 @@
package cacheops.cache.definition.data
inline class MapTile(val hash: Long) {
constructor(
height: Int = 0,
opcode: Int = 0,
overlay: Int = 0,
path: Int = 0,
rotation: Int = 0,
settings: Int = 0,
underlay: Int = 0
) : this(getHash(height, opcode, overlay, path, rotation, settings, underlay))
val height: Int
get() = getHeight(hash)
val attrOpcode: Int
get() = getOpcode(hash)
val overlayId: Int
get() = getOverlay(hash)
val overlayPath: Int
get() = getPath(hash)
val overlayRotation: Int
get() = getRotation(hash)
val settings: Int
get() = getSettings(hash)
val underlayId: Int
get() = getUnderlay(hash)
fun isTile(flag: Int) = settings and flag == flag
companion object {
val EMPTY = MapTile()
fun getHash(height: Int, opcode: Int, overlay: Int, path: Int, rotation: Int, settings: Int, underlay: Int): Long {
return getHash(height.toLong(), opcode.toLong(), overlay.toLong(), path.toLong(), rotation.toLong(), settings.toLong(), underlay.toLong())
}
fun getHash(height: Long, opcode: Long, overlay: Long, path: Long, rotation: Long, settings: Long, underlay: Long): Long {
return height + (opcode shl 8) + (overlay shl 16) + (path shl 24) + (rotation shl 32) + (settings shl 40) + (underlay shl 48)
}
fun getHeight(hash: Long): Int = (hash and 0xff).toInt()
fun getOpcode(hash: Long): Int = (hash shr 8 and 0xff).toInt()
fun getOverlay(hash: Long): Int = (hash shr 16 and 0xff).toInt()
fun getPath(hash: Long): Int = (hash shr 24 and 0xff).toInt()
fun getRotation(hash: Long): Int = (hash shr 32 and 0xff).toInt()
fun getSettings(hash: Long): Int = (hash shr 40 and 0xff).toInt()
fun getUnderlay(hash: Long): Int = (hash shr 48 and 0xff).toInt()
}
}

View file

@ -0,0 +1,250 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
import cacheops.cache.definition.Extra
import cacheops.cache.definition.Parameterized
import cacheops.cache.definition.Recolourable
data class NPCDefinition(
override var id: Int = -1,
var modelIds: IntArray? = null,
var name: String = "null",
var size: Int = 1,
var options: Array<String?> = arrayOf(null, null, null, null, null, "Examine"),
override var originalColours: ShortArray? = null,
override var modifiedColours: ShortArray? = null,
override var originalTextureColours: ShortArray? = null,
override var modifiedTextureColours: ShortArray? = null,
var recolourPalette: ByteArray? = null,
var dialogueModels: IntArray? = null,
var drawMinimapDot: Boolean = true,
var combat: Int = -1,
var scaleXY: Int = 128,
var scaleZ: Int = 128,
var priorityRender: Boolean = false,
var lightModifier: Int = 0,
var shadowModifier: Int = 0,
var headIcon: Int = -1,
var rotation: Int = 32,
var varbit: Int = -1,
var varp: Int = -1,
var morphs: IntArray? = null,
var clickable: Boolean = true,
var slowWalk: Boolean = true,
var animateIdle: Boolean = true,
var primaryShadowColour: Short = 0,
var secondaryShadowColour: Short = 0,
var primaryShadowModifier: Byte = -96,
var secondaryShadowModifier: Byte = -16,
var walkMask: Byte = 0,
var translations: Array<IntArray?>? = null,
var hitbarSprite: Int = -1,
var height: Int = -1,
var respawnDirection: Byte = 4,
var renderEmote: Int = -1,
var idleSound: Int = -1,
var crawlSound: Int = -1,
var walkSound: Int = -1,
var runSound: Int = -1,
var soundDistance: Int = 0,
var primaryCursorOp: Int = -1,
var primaryCursor: Int = -1,
var secondaryCursorOp: Int = -1,
var secondaryCursor: Int = -1,
var attackCursor: Int = -1,
var armyIcon: Int = -1,
var spriteId: Int = -1,
var ambientSoundVolume: Int = 255,
var visiblePriority: Boolean = false,
var mapFunction: Int = -1,
var invisiblePriority: Boolean = false,
var hue: Byte = 0,
var saturation: Byte = 0,
var lightness: Byte = 0,
var opacity: Byte = 0,
var mainOptionIndex: Byte = -1,
var campaigns: IntArray? = null,
var aBoolean2883: Boolean = false,
var anInt2803: Int = -1,
var anInt2844: Int = 256,
var anInt2852: Int = 256,
var anInt2831: Int = 0,
var anInt2862: Int = 0,
override var params: HashMap<Long, Any>? = null,
override var extras: Map<String, Any> = emptyMap()
) : Definition, Recolourable, Parameterized, Extra {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as NPCDefinition
if (id != other.id) return false
if (modelIds != null) {
if (other.modelIds == null) return false
if (!modelIds!!.contentEquals(other.modelIds!!)) return false
} else if (other.modelIds != null) return false
if (name != other.name) return false
if (size != other.size) return false
if (!options.contentEquals(other.options)) return false
if (originalColours != null) {
if (other.originalColours == null) return false
if (!originalColours!!.contentEquals(other.originalColours!!)) return false
} else if (other.originalColours != null) return false
if (modifiedColours != null) {
if (other.modifiedColours == null) return false
if (!modifiedColours!!.contentEquals(other.modifiedColours!!)) return false
} else if (other.modifiedColours != null) return false
if (originalTextureColours != null) {
if (other.originalTextureColours == null) return false
if (!originalTextureColours!!.contentEquals(other.originalTextureColours!!)) return false
} else if (other.originalTextureColours != null) return false
if (modifiedTextureColours != null) {
if (other.modifiedTextureColours == null) return false
if (!modifiedTextureColours!!.contentEquals(other.modifiedTextureColours!!)) return false
} else if (other.modifiedTextureColours != null) return false
if (recolourPalette != null) {
if (other.recolourPalette == null) return false
if (!recolourPalette!!.contentEquals(other.recolourPalette!!)) return false
} else if (other.recolourPalette != null) return false
if (dialogueModels != null) {
if (other.dialogueModels == null) return false
if (!dialogueModels!!.contentEquals(other.dialogueModels!!)) return false
} else if (other.dialogueModels != null) return false
if (drawMinimapDot != other.drawMinimapDot) return false
if (combat != other.combat) return false
if (scaleXY != other.scaleXY) return false
if (scaleZ != other.scaleZ) return false
if (priorityRender != other.priorityRender) return false
if (lightModifier != other.lightModifier) return false
if (shadowModifier != other.shadowModifier) return false
if (headIcon != other.headIcon) return false
if (rotation != other.rotation) return false
if (varbit != other.varbit) return false
if (varp != other.varp) return false
if (morphs != null) {
if (other.morphs == null) return false
if (!morphs!!.contentEquals(other.morphs!!)) return false
} else if (other.morphs != null) return false
if (clickable != other.clickable) return false
if (slowWalk != other.slowWalk) return false
if (animateIdle != other.animateIdle) return false
if (primaryShadowColour != other.primaryShadowColour) return false
if (secondaryShadowColour != other.secondaryShadowColour) return false
if (primaryShadowModifier != other.primaryShadowModifier) return false
if (secondaryShadowModifier != other.secondaryShadowModifier) return false
if (walkMask != other.walkMask) return false
if (translations != null) {
if (other.translations == null) return false
if (!translations!!.contentDeepEquals(other.translations!!)) return false
} else if (other.translations != null) return false
if (hitbarSprite != other.hitbarSprite) return false
if (height != other.height) return false
if (respawnDirection != other.respawnDirection) return false
if (renderEmote != other.renderEmote) return false
if (idleSound != other.idleSound) return false
if (crawlSound != other.crawlSound) return false
if (walkSound != other.walkSound) return false
if (runSound != other.runSound) return false
if (soundDistance != other.soundDistance) return false
if (primaryCursorOp != other.primaryCursorOp) return false
if (primaryCursor != other.primaryCursor) return false
if (secondaryCursorOp != other.secondaryCursorOp) return false
if (secondaryCursor != other.secondaryCursor) return false
if (attackCursor != other.attackCursor) return false
if (armyIcon != other.armyIcon) return false
if (spriteId != other.spriteId) return false
if (ambientSoundVolume != other.ambientSoundVolume) return false
if (visiblePriority != other.visiblePriority) return false
if (mapFunction != other.mapFunction) return false
if (invisiblePriority != other.invisiblePriority) return false
if (hue != other.hue) return false
if (saturation != other.saturation) return false
if (lightness != other.lightness) return false
if (opacity != other.opacity) return false
if (mainOptionIndex != other.mainOptionIndex) return false
if (campaigns != null) {
if (other.campaigns == null) return false
if (!campaigns!!.contentEquals(other.campaigns!!)) return false
} else if (other.campaigns != null) return false
if (aBoolean2883 != other.aBoolean2883) return false
if (anInt2803 != other.anInt2803) return false
if (anInt2844 != other.anInt2844) return false
if (anInt2852 != other.anInt2852) return false
if (anInt2831 != other.anInt2831) return false
if (anInt2862 != other.anInt2862) return false
if (params != other.params) return false
if (extras != other.extras) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + (modelIds?.contentHashCode() ?: 0)
result = 31 * result + name.hashCode()
result = 31 * result + size
result = 31 * result + options.contentHashCode()
result = 31 * result + (originalColours?.contentHashCode() ?: 0)
result = 31 * result + (modifiedColours?.contentHashCode() ?: 0)
result = 31 * result + (originalTextureColours?.contentHashCode() ?: 0)
result = 31 * result + (modifiedTextureColours?.contentHashCode() ?: 0)
result = 31 * result + (recolourPalette?.contentHashCode() ?: 0)
result = 31 * result + (dialogueModels?.contentHashCode() ?: 0)
result = 31 * result + drawMinimapDot.hashCode()
result = 31 * result + combat
result = 31 * result + scaleXY
result = 31 * result + scaleZ
result = 31 * result + priorityRender.hashCode()
result = 31 * result + lightModifier
result = 31 * result + shadowModifier
result = 31 * result + headIcon
result = 31 * result + rotation
result = 31 * result + varbit
result = 31 * result + varp
result = 31 * result + (morphs?.contentHashCode() ?: 0)
result = 31 * result + clickable.hashCode()
result = 31 * result + slowWalk.hashCode()
result = 31 * result + animateIdle.hashCode()
result = 31 * result + primaryShadowColour
result = 31 * result + secondaryShadowColour
result = 31 * result + primaryShadowModifier
result = 31 * result + secondaryShadowModifier
result = 31 * result + walkMask
result = 31 * result + (translations?.contentDeepHashCode() ?: 0)
result = 31 * result + hitbarSprite
result = 31 * result + height
result = 31 * result + respawnDirection
result = 31 * result + renderEmote
result = 31 * result + idleSound
result = 31 * result + crawlSound
result = 31 * result + walkSound
result = 31 * result + runSound
result = 31 * result + soundDistance
result = 31 * result + primaryCursorOp
result = 31 * result + primaryCursor
result = 31 * result + secondaryCursorOp
result = 31 * result + secondaryCursor
result = 31 * result + attackCursor
result = 31 * result + armyIcon
result = 31 * result + spriteId
result = 31 * result + ambientSoundVolume
result = 31 * result + visiblePriority.hashCode()
result = 31 * result + mapFunction
result = 31 * result + invisiblePriority.hashCode()
result = 31 * result + hue
result = 31 * result + saturation
result = 31 * result + lightness
result = 31 * result + opacity
result = 31 * result + mainOptionIndex
result = 31 * result + (campaigns?.contentHashCode() ?: 0)
result = 31 * result + aBoolean2883.hashCode()
result = 31 * result + anInt2803
result = 31 * result + anInt2844
result = 31 * result + anInt2852
result = 31 * result + anInt2831
result = 31 * result + anInt2862
result = 31 * result + (params?.hashCode() ?: 0)
result = 31 * result + extras.hashCode()
return result
}
}

View file

@ -0,0 +1,295 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
import cacheops.cache.definition.ColorPalette
import cacheops.cache.definition.Extra
import cacheops.cache.definition.Parameterized
import cacheops.cache.definition.Recolourable
data class ObjectDefinition(
override var id: Int = -1,
var modelIds: IntArray? = null,
var modelTypes: IntArray? = null,
var name: String = "null",
var sizeX: Int = 1,
var sizeY: Int = 1,
var blocksSky: Boolean = true,
var solid: Int = 2,
var interactive: Int = -1,
var contouredGround: Byte = 0,
var delayShading: Boolean = false,
var offsetMultiplier: Int = 64,
var brightness: Int = 0,
var options: Array<String?> = arrayOf(null, null, null, null, null, "Examine"),
var contrast: Int = 0,
override var originalColours: ShortArray? = null,
override var modifiedColours: ShortArray? = null,
override var originalTextureColours: ShortArray? = null,
override var modifiedTextureColours: ShortArray? = null,
override var recolourPalette: ByteArray? = null,
var mirrored: Boolean = false,
var castsShadow: Boolean = true,
var modelSizeX: Int = 128,
var modelSizeZ: Int = 128,
var modelSizeY: Int = 128,
var blockFlag: Int = 0,
var offsetX: Int = 0,
var offsetZ: Int = 0,
var offsetY: Int = 0,
var blocksLand: Boolean = false,
var ignoreOnRoute: Boolean = false,
var supportItems: Int = -1,
var varbitIndex: Int = -1,
var configId: Int = -1,
var configObjectIds: IntArray? = null,
var anInt3015: Int = -1,
var anInt3012: Int = 0,
var anInt2989: Int = 0,
var anInt2971: Int = 0,
var anIntArray3036: IntArray? = null,
var anInt3023: Int = -1,
var hideMinimap: Boolean = false,
var aBoolean2972: Boolean = true,
var animateImmediately: Boolean = true,
var aBoolean1502: Boolean = false,
var aBoolean1507: Boolean = false,
var isMembers: Boolean = false,
var adjustMapSceneRotation: Boolean = false,
var hasAnimation: Boolean = false,
var anInt2987: Int = -1,
var anInt3008: Int = -1,
var anInt3038: Int = -1,
var anInt3013: Int = -1,
var anInt2958: Int = 0,
var mapscene: Int = -1,
var culling: Int = -1,
var anInt3024: Int = 255,
var invertMapScene: Boolean = false,
var animations: IntArray? = null,
var percents: IntArray? = null,
var mapDefinitionId: Int = -1,
var anIntArray2981: IntArray? = null,
var aByte2974: Byte = 0,
var aByte3045: Byte = 0,
var aByte3052: Byte = 0,
var aByte2960: Byte = 0,
var anInt2964: Int = 0,
var anInt2963: Int = 0,
var anInt3018: Int = 0,
var anInt2983: Int = 0,
var aBoolean2961: Boolean = false,
var aBoolean2993: Boolean = false,
var anInt3032: Int = 960,
var anInt2962: Int = 0,
var anInt3050: Int = 256,
var anInt3020: Int = 256,
var aBoolean2992: Boolean = false,
var anInt2975: Int = 0,
override var params: HashMap<Long, Any>? = null,
override var extras: Map<String, Any> = emptyMap()
) : Definition, Recolourable, ColorPalette, Parameterized, Extra {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ObjectDefinition
if (id != other.id) return false
if (modelIds != null) {
if (other.modelIds == null) return false
if (!modelIds!!.contentEquals(other.modelIds!!)) return false
} else if (other.modelIds != null) return false
if (modelTypes != null) {
if (other.modelTypes == null) return false
if (!modelTypes!!.contentEquals(other.modelTypes!!)) return false
} else if (other.modelTypes != null) return false
if (name != other.name) return false
if (sizeX != other.sizeX) return false
if (sizeY != other.sizeY) return false
if (blocksSky != other.blocksSky) return false
if (solid != other.solid) return false
if (interactive != other.interactive) return false
if (contouredGround != other.contouredGround) return false
if (delayShading != other.delayShading) return false
if (offsetMultiplier != other.offsetMultiplier) return false
if (brightness != other.brightness) return false
if (!options.contentEquals(other.options)) return false
if (contrast != other.contrast) return false
if (originalColours != null) {
if (other.originalColours == null) return false
if (!originalColours!!.contentEquals(other.originalColours!!)) return false
} else if (other.originalColours != null) return false
if (modifiedColours != null) {
if (other.modifiedColours == null) return false
if (!modifiedColours!!.contentEquals(other.modifiedColours!!)) return false
} else if (other.modifiedColours != null) return false
if (originalTextureColours != null) {
if (other.originalTextureColours == null) return false
if (!originalTextureColours!!.contentEquals(other.originalTextureColours!!)) return false
} else if (other.originalTextureColours != null) return false
if (modifiedTextureColours != null) {
if (other.modifiedTextureColours == null) return false
if (!modifiedTextureColours!!.contentEquals(other.modifiedTextureColours!!)) return false
} else if (other.modifiedTextureColours != null) return false
if (recolourPalette != null) {
if (other.recolourPalette == null) return false
if (!recolourPalette!!.contentEquals(other.recolourPalette!!)) return false
} else if (other.recolourPalette != null) return false
if (mirrored != other.mirrored) return false
if (castsShadow != other.castsShadow) return false
if (modelSizeX != other.modelSizeX) return false
if (modelSizeZ != other.modelSizeZ) return false
if (modelSizeY != other.modelSizeY) return false
if (blockFlag != other.blockFlag) return false
if (offsetX != other.offsetX) return false
if (offsetZ != other.offsetZ) return false
if (offsetY != other.offsetY) return false
if (blocksLand != other.blocksLand) return false
if (ignoreOnRoute != other.ignoreOnRoute) return false
if (supportItems != other.supportItems) return false
if (varbitIndex != other.varbitIndex) return false
if (configId != other.configId) return false
if (configObjectIds != null) {
if (other.configObjectIds == null) return false
if (!configObjectIds!!.contentEquals(other.configObjectIds!!)) return false
} else if (other.configObjectIds != null) return false
if (anInt3015 != other.anInt3015) return false
if (anInt3012 != other.anInt3012) return false
if (anInt2989 != other.anInt2989) return false
if (anInt2971 != other.anInt2971) return false
if (anIntArray3036 != null) {
if (other.anIntArray3036 == null) return false
if (!anIntArray3036!!.contentEquals(other.anIntArray3036!!)) return false
} else if (other.anIntArray3036 != null) return false
if (anInt3023 != other.anInt3023) return false
if (hideMinimap != other.hideMinimap) return false
if (aBoolean2972 != other.aBoolean2972) return false
if (animateImmediately != other.animateImmediately) return false
if (isMembers != other.isMembers) return false
if (adjustMapSceneRotation != other.adjustMapSceneRotation) return false
if (hasAnimation != other.hasAnimation) return false
if (anInt2987 != other.anInt2987) return false
if (anInt3008 != other.anInt3008) return false
if (anInt3038 != other.anInt3038) return false
if (anInt3013 != other.anInt3013) return false
if (anInt2958 != other.anInt2958) return false
if (mapscene != other.mapscene) return false
if (culling != other.culling) return false
if (anInt3024 != other.anInt3024) return false
if (invertMapScene != other.invertMapScene) return false
if (animations != null) {
if (other.animations == null) return false
if (!animations!!.contentEquals(other.animations!!)) return false
} else if (other.animations != null) return false
if (percents != null) {
if (other.percents == null) return false
if (!percents!!.contentEquals(other.percents!!)) return false
} else if (other.percents != null) return false
if (mapDefinitionId != other.mapDefinitionId) return false
if (anIntArray2981 != null) {
if (other.anIntArray2981 == null) return false
if (!anIntArray2981!!.contentEquals(other.anIntArray2981!!)) return false
} else if (other.anIntArray2981 != null) return false
if (aByte2974 != other.aByte2974) return false
if (aByte3045 != other.aByte3045) return false
if (aByte3052 != other.aByte3052) return false
if (aByte2960 != other.aByte2960) return false
if (anInt2964 != other.anInt2964) return false
if (anInt2963 != other.anInt2963) return false
if (anInt3018 != other.anInt3018) return false
if (anInt2983 != other.anInt2983) return false
if (aBoolean2961 != other.aBoolean2961) return false
if (aBoolean2993 != other.aBoolean2993) return false
if (anInt3032 != other.anInt3032) return false
if (anInt2962 != other.anInt2962) return false
if (anInt3050 != other.anInt3050) return false
if (anInt3020 != other.anInt3020) return false
if (aBoolean2992 != other.aBoolean2992) return false
if (anInt2975 != other.anInt2975) return false
if (params != other.params) return false
if (extras != other.extras) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + (modelIds?.contentHashCode() ?: 0)
result = 31 * result + (modelTypes?.contentHashCode() ?: 0)
result = 31 * result + name.hashCode()
result = 31 * result + sizeX
result = 31 * result + sizeY
result = 31 * result + blocksSky.hashCode()
result = 31 * result + solid
result = 31 * result + interactive
result = 31 * result + contouredGround
result = 31 * result + delayShading.hashCode()
result = 31 * result + offsetMultiplier
result = 31 * result + brightness
result = 31 * result + options.contentHashCode()
result = 31 * result + contrast
result = 31 * result + (originalColours?.contentHashCode() ?: 0)
result = 31 * result + (modifiedColours?.contentHashCode() ?: 0)
result = 31 * result + (originalTextureColours?.contentHashCode() ?: 0)
result = 31 * result + (modifiedTextureColours?.contentHashCode() ?: 0)
result = 31 * result + (recolourPalette?.contentHashCode() ?: 0)
result = 31 * result + mirrored.hashCode()
result = 31 * result + castsShadow.hashCode()
result = 31 * result + modelSizeX
result = 31 * result + modelSizeZ
result = 31 * result + modelSizeY
result = 31 * result + blockFlag
result = 31 * result + offsetX
result = 31 * result + offsetZ
result = 31 * result + offsetY
result = 31 * result + blocksLand.hashCode()
result = 31 * result + ignoreOnRoute.hashCode()
result = 31 * result + supportItems
result = 31 * result + varbitIndex
result = 31 * result + configId
result = 31 * result + (configObjectIds?.contentHashCode() ?: 0)
result = 31 * result + anInt3015
result = 31 * result + anInt3012
result = 31 * result + anInt2989
result = 31 * result + anInt2971
result = 31 * result + (anIntArray3036?.contentHashCode() ?: 0)
result = 31 * result + anInt3023
result = 31 * result + hideMinimap.hashCode()
result = 31 * result + aBoolean2972.hashCode()
result = 31 * result + animateImmediately.hashCode()
result = 31 * result + isMembers.hashCode()
result = 31 * result + adjustMapSceneRotation.hashCode()
result = 31 * result + hasAnimation.hashCode()
result = 31 * result + anInt2987
result = 31 * result + anInt3008
result = 31 * result + anInt3038
result = 31 * result + anInt3013
result = 31 * result + anInt2958
result = 31 * result + mapscene
result = 31 * result + culling
result = 31 * result + anInt3024
result = 31 * result + invertMapScene.hashCode()
result = 31 * result + (animations?.contentHashCode() ?: 0)
result = 31 * result + (percents?.contentHashCode() ?: 0)
result = 31 * result + mapDefinitionId
result = 31 * result + (anIntArray2981?.contentHashCode() ?: 0)
result = 31 * result + aByte2974
result = 31 * result + aByte3045
result = 31 * result + aByte3052
result = 31 * result + aByte2960
result = 31 * result + anInt2964
result = 31 * result + anInt2963
result = 31 * result + anInt3018
result = 31 * result + anInt2983
result = 31 * result + aBoolean2961.hashCode()
result = 31 * result + aBoolean2993.hashCode()
result = 31 * result + anInt3032
result = 31 * result + anInt2962
result = 31 * result + anInt3050
result = 31 * result + anInt3020
result = 31 * result + aBoolean2992.hashCode()
result = 31 * result + anInt2975
result = 31 * result + (params?.hashCode() ?: 0)
result = 31 * result + extras.hashCode()
return result
}
}

View file

@ -0,0 +1,36 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
@Suppress("ArrayInDataClass")
data class QuickChatOptionDefinition(
override var id: Int = -1,
var optionText: String? = null,
var quickReplyOptions: IntArray? = null,
var navigateChars: CharArray? = null,
var dynamicData: IntArray? = null,
var staticData: CharArray? = null
) : Definition {
fun getDynamicIndex(c: Char): Int {
if (dynamicData == null) {
return -1
}
for (i in dynamicData!!.indices) {
if (staticData!![i] == c) {
return dynamicData!![i]
}
}
return -1
}
fun getOption(c: Char): Int {
if (quickReplyOptions == null) {
return -1
}
for (i in quickReplyOptions!!.indices) {
if (navigateChars!![i] == c) {
return quickReplyOptions!![i]
}
}
return -1
}
}

View file

@ -0,0 +1,8 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
@Suppress("ArrayInDataClass")
data class SpriteDefinition(
override var id: Int = -1,
var sprites: Array<IndexedSprite>? = null
) : Definition

View file

@ -0,0 +1,25 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
data class TextureDefinition(
override var id: Int = -1,
var useTextureColour: Boolean = false,
var aBoolean1204: Boolean = false,
var aBoolean1205: Boolean = false,
var aByte1217: Byte = 0,
var aByte1225: Byte = 0,
var type: Byte = 0,
var aByte1213: Byte = 0,
var colour: Int = 0,
var aByte1211: Byte = 0,
var aByte1203: Byte = 0,
var aBoolean1222: Boolean = false,
var aBoolean1216: Boolean = false,
var aByte1207: Byte = 0,
var aBoolean1212: Boolean = false,
var aBoolean1210: Boolean = false,
var aBoolean1215: Boolean = false,
var anInt1202: Int = 0,
var anInt1206: Int = 0,
var anInt1226: Int = 0
) : Definition

View file

@ -0,0 +1,9 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
data class VarBitDefinition(
override var id: Int = -1,
var index: Int = 0,
var leastSignificantBit: Int = 0,
var mostSignificantBit: Int = 0
) : Definition

View file

@ -0,0 +1,18 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
import java.util.*
data class WorldMapDefinition(
override var id: Int = -1,
var map: String = "",
var name: String = "",
var position: Int = -1,
var anInt9542: Int = -1,
var static: Boolean = false,
var anInt9547: Int = -1,
var sections: LinkedList<WorldMapSection>? = null,
var minX: Int = 12800,
var minY: Int = 12800,
var maxX: Int = 0,
var maxY: Int = 0
) : Definition

View file

@ -0,0 +1,6 @@
package cacheops.cache.definition.data
data class WorldMapIcon(
var id: Int = -1,
var position: Int = -1
)

View file

@ -0,0 +1,25 @@
package cacheops.cache.definition.data
import cacheops.cache.Definition
data class WorldMapIconDefinition(
override var id: Int = -1,
var icons: Array<WorldMapIcon> = emptyArray()
) : Definition {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as WorldMapIconDefinition
if (id != other.id) return false
if (!icons.contentEquals(other.icons)) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + icons.contentHashCode()
return result
}
}

View file

@ -0,0 +1,3 @@
package cacheops.cache.definition.data
data class WorldMapSection(val plane: Int, val minX: Int, val minY: Int, val maxX: Int, val maxY: Int, var startX: Int, var startY: Int, var endX: Int, var endY: Int)

View file

@ -0,0 +1,236 @@
package cacheops.cache.definition.decoder
import cacheops.cache.Cache
import cacheops.cache.DefinitionDecoder
import cacheops.cache.buffer.read.Reader
import cacheops.cache.definition.data.ItemDefinition
import const.Indices
class ItemDecoder(cache: Cache) : DefinitionDecoder<ItemDefinition>(cache, Indices.CONFIGURATION_ITEMS) {
override fun create() = ItemDefinition()
override fun getFile(id: Int) = id and 0xff
override fun getArchive(id: Int) = id ushr 8
override fun ItemDefinition.read(opcode: Int, buffer: Reader) {
when (opcode) {
1 -> modelId = buffer.readShort()
2 -> name = buffer.readString()
4 -> spriteScale = buffer.readShort()
5 -> spritePitch = buffer.readShort()
6 -> spriteCameraRoll = buffer.readShort()
7 -> {
spriteTranslateX = buffer.readShort()
if (spriteTranslateX > 32767) {
spriteTranslateX -= 65536
}
}
8 -> {
spriteTranslateY = buffer.readShort()
if (spriteTranslateY > 32767) {
spriteTranslateY -= 65536
}
}
11 -> stackable = 1
12 -> cost = buffer.readInt()
16 -> members = true
18 -> multiStackSize = buffer.readShort()
23 -> primaryMaleModel = buffer.readUnsignedShort()
24 -> secondaryMaleModel = buffer.readUnsignedShort()
25 -> primaryFemaleModel = buffer.readUnsignedShort()
26 -> secondaryFemaleModel = buffer.readUnsignedShort()
in 30..34 -> floorOptions[opcode - 30] = buffer.readString()
in 35..39 -> options[opcode - 35] = buffer.readString()
40 -> readColours(buffer)
41 -> readTextures(buffer)
42 -> readColourPalette(buffer)
65 -> exchangeable = true
78 -> tertiaryMaleModel = buffer.readShort()
79 -> tertiaryFemaleModel = buffer.readShort()
90 -> primaryMaleDialogueHead = buffer.readShort()
91 -> primaryFemaleDialogueHead = buffer.readShort()
92 -> secondaryMaleDialogueHead = buffer.readShort()
93 -> secondaryFemaleDialogueHead = buffer.readShort()
95 -> spriteCameraYaw = buffer.readShort()
96 -> dummyItem = buffer.readUnsignedByte()
97 -> noteId = buffer.readShort()
98 -> notedTemplateId = buffer.readShort()
in 100..109 -> {
if (stackIds == null) {
stackAmounts = IntArray(10)
stackIds = IntArray(10)
}
stackIds!![opcode - 100] = buffer.readShort()
stackAmounts!![opcode - 100] = buffer.readShort()
}
110 -> floorScaleX = buffer.readShort()
111 -> floorScaleZ = buffer.readShort()
112 -> floorScaleY = buffer.readShort()
113 -> ambience = buffer.readByte()
114 -> diffusion = buffer.readByte() * 5
115 -> team = buffer.readUnsignedByte()
121 -> lendId = buffer.readShort()
122 -> lendTemplateId = buffer.readShort()
125 -> {
maleWieldX = buffer.readByte() shl 2
maleWieldZ = buffer.readByte() shl 2
maleWieldY = buffer.readByte() shl 2
}
126 -> {
femaleWieldX = buffer.readByte() shl 2
femaleWieldZ = buffer.readByte() shl 2
femaleWieldY = buffer.readByte() shl 2
}
127 -> {
primaryCursorOpcode = buffer.readUnsignedByte()
primaryCursor = buffer.readShort()
}
128 -> {
secondaryCursorOpcode = buffer.readUnsignedByte()
secondaryCursor = buffer.readShort()
}
129 -> {
primaryInterfaceCursorOpcode = buffer.readUnsignedByte()
primaryInterfaceCursor = buffer.readShort()
}
130 -> {
secondaryInterfaceCursorOpcode = buffer.readUnsignedByte()
secondaryInterfaceCursor = buffer.readShort()
}
132 -> {
val length = buffer.readUnsignedByte()
campaigns = IntArray(length)
repeat(length) { count ->
campaigns!![count] = buffer.readShort()
}
}
134 -> pickSizeShift = buffer.readUnsignedByte()
139 -> singleNoteId = buffer.readShort()
140 -> singleNoteTemplateId = buffer.readShort()
249 -> readParameters(buffer)
}
}
override fun ItemDefinition.changeValues() {
if (notedTemplateId != -1) {
toNote(getOrNull(notedTemplateId), getOrNull(noteId))
}
if (lendTemplateId != -1) {
toLend(getOrNull(lendId), getOrNull(lendTemplateId))
}
if (singleNoteTemplateId != -1) {
toSingleNote(getOrNull(singleNoteTemplateId), getOrNull(singleNoteId))
}
}
fun ItemDefinition.toLend(item: ItemDefinition?, template: ItemDefinition?) {
if (item == null || template == null) {
return
}
modifiedColours = item.modifiedColours
primaryMaleDialogueHead = item.primaryMaleDialogueHead
secondaryMaleDialogueHead = item.secondaryMaleDialogueHead
tertiaryMaleModel = item.tertiaryMaleModel
team = item.team
params = item.params
members = item.members
modifiedTextureColours = item.modifiedTextureColours
maleWieldZ = item.maleWieldZ
secondaryFemaleModel = item.secondaryFemaleModel
spriteCameraYaw = template.spriteCameraYaw
floorOptions = item.floorOptions
secondaryFemaleDialogueHead = item.secondaryFemaleDialogueHead
recolourPalette = item.recolourPalette
femaleWieldZ = item.femaleWieldZ
spritePitch = template.spritePitch
primaryFemaleModel = item.primaryFemaleModel
modelId = template.modelId
options = arrayOfNulls(5)
spriteCameraRoll = template.spriteCameraRoll
spriteTranslateY = template.spriteTranslateY
originalTextureColours = item.originalTextureColours
femaleWieldX = item.femaleWieldX
secondaryMaleModel = item.secondaryMaleModel
cost = 0
maleWieldY = item.maleWieldY
originalColours = item.originalColours
spriteTranslateX = template.spriteTranslateX
femaleWieldY = item.femaleWieldY
primaryFemaleDialogueHead = item.primaryFemaleDialogueHead
spriteScale = template.spriteScale
name = item.name
tertiaryFemaleModel = item.tertiaryFemaleModel
primaryMaleModel = item.primaryMaleModel
maleWieldX = item.maleWieldX
System.arraycopy(item.options, 0, options, 0, 4)
options[4] = "Discard"
}
fun ItemDefinition.toNote(template: ItemDefinition?, item: ItemDefinition?) {
if (item == null || template == null) {
return
}
spriteTranslateY = template.spriteTranslateY
originalColours = template.originalColours
cost = item.cost
name = item.name
modifiedTextureColours = template.modifiedTextureColours
spriteCameraRoll = template.spriteCameraRoll
spriteCameraYaw = template.spriteCameraYaw
originalTextureColours = template.originalTextureColours
modelId = template.modelId
spriteScale = template.spriteScale
recolourPalette = template.recolourPalette
stackable = 1
spritePitch = template.spritePitch
spriteTranslateX = template.spriteTranslateX
members = item.members
modifiedColours = template.modifiedColours
}
fun ItemDefinition.toSingleNote(template: ItemDefinition?, item: ItemDefinition?) {
if (item == null || template == null) {
return
}
cost = 0
tertiaryMaleModel = item.tertiaryMaleModel
stackable = item.stackable
members = item.members
recolourPalette = item.recolourPalette
spriteTranslateY = template.spriteTranslateY
team = item.team
secondaryMaleModel = item.secondaryMaleModel
options = arrayOfNulls(5)
floorOptions = item.floorOptions
maleWieldZ = item.maleWieldZ
primaryMaleDialogueHead = item.primaryMaleDialogueHead
femaleWieldZ = item.femaleWieldZ
name = item.name
spriteScale = template.spriteScale
originalColours = item.originalColours
secondaryFemaleDialogueHead = item.secondaryFemaleDialogueHead
params = item.params
primaryFemaleModel = item.primaryFemaleModel
spritePitch = template.spritePitch
spriteCameraRoll = template.spriteCameraRoll
femaleWieldX = item.femaleWieldX
secondaryMaleDialogueHead = item.secondaryMaleDialogueHead
tertiaryFemaleModel = item.tertiaryFemaleModel
modifiedTextureColours = item.modifiedTextureColours
maleWieldX = item.maleWieldX
primaryFemaleDialogueHead = item.primaryFemaleDialogueHead
modelId = template.modelId
modifiedColours = item.modifiedColours
secondaryFemaleModel = item.secondaryFemaleModel
spriteTranslateX = template.spriteTranslateX
spriteCameraYaw = template.spriteCameraYaw
primaryMaleModel = item.primaryMaleModel
femaleWieldY = item.femaleWieldY
maleWieldY = item.maleWieldY
originalTextureColours = item.originalTextureColours
System.arraycopy(item.options, 0, options, 0, 4)
options[4] = "Discard"
}
}

View file

@ -0,0 +1,179 @@
package cacheops.cache.definition.decoder
import cacheops.cache.Cache
import cacheops.cache.DefinitionDecoder
import cacheops.cache.buffer.read.Reader
import cacheops.cache.definition.data.NPCDefinition
import const.Indices
class NPCDecoder(cache: Cache, val member: Boolean) : DefinitionDecoder<NPCDefinition>(cache, Indices.CONFIGURATION_NPCS) {
override fun create() = NPCDefinition()
override fun getFile(id: Int) = id and 0x7f
override fun getArchive(id: Int) = id ushr 7
override fun NPCDefinition.read(opcode: Int, buffer: Reader) {
when (opcode) {
1 -> {
val length = buffer.readUnsignedByte()
modelIds = IntArray(length)
repeat(length) { count ->
modelIds!![count] = buffer.readShort()
if (modelIds!![count] == 65535) {
modelIds!![count] = -1
}
}
}
2 -> name = buffer.readString()
12 -> size = buffer.readUnsignedByte()
in 30..34 -> options[-30 + opcode] = buffer.readString()
40 -> readColours(buffer)
41 -> readTextures(buffer)
42 -> {
val length = buffer.readUnsignedByte()
recolourPalette = ByteArray(length)
repeat(length) { count ->
recolourPalette!![count] = buffer.readByte().toByte()
}
}
60 -> {
val length = buffer.readUnsignedByte()
dialogueModels = IntArray(length)
repeat(length) { count ->
dialogueModels!![count] = buffer.readShort()
}
}
93 -> drawMinimapDot = false
95 -> combat = buffer.readShort()
97 -> scaleXY = buffer.readShort()
98 -> scaleZ = buffer.readShort()
99 -> priorityRender = true
100 -> lightModifier = buffer.readByte()
101 -> shadowModifier = 5 * buffer.readByte()
102 -> headIcon = buffer.readShort()
103 -> rotation = buffer.readShort()
106, 118 -> {
varbit = buffer.readShort()
if (varbit == 65535) {
varbit = -1
}
varp = buffer.readShort()
if (varp == 65535) {
varp = -1
}
var last = -1
if (opcode == 118) {
last = buffer.readShort()
if (last == 65535) {
last = -1
}
}
val count = buffer.readUnsignedByte()
morphs = IntArray(count + 2)
for (index in 0..count) {
morphs!![index] = buffer.readShort()
if (morphs!![index] == 65535) {
morphs!![index] = -1
}
}
morphs!![count + 1] = last
}
107 -> clickable = false
109 -> slowWalk = false
111 -> animateIdle = false
113 -> {
primaryShadowColour = buffer.readShort().toShort()
secondaryShadowColour = buffer.readShort().toShort()
}
114 -> {
primaryShadowModifier = buffer.readByte().toByte()
secondaryShadowModifier = buffer.readByte().toByte()
}
119 -> walkMask = buffer.readByte().toByte()
121 -> {
translations = arrayOfNulls(modelIds!!.size)
val length = buffer.readUnsignedByte()
repeat(length) {
val index = buffer.readUnsignedByte()
translations!![index] = intArrayOf(
buffer.readByte(),
buffer.readByte(),
buffer.readByte()
)
}
}
122 -> hitbarSprite = buffer.readShort()
123 -> height = buffer.readShort()
125 -> respawnDirection = buffer.readByte().toByte()
127 -> renderEmote = buffer.readShort()
128 -> buffer.readUnsignedByte()
134 -> {
idleSound = buffer.readShort()
if (idleSound == 65535) {
idleSound = -1
}
crawlSound = buffer.readShort()
if (crawlSound == 65535) {
crawlSound = -1
}
walkSound = buffer.readShort()
if (walkSound == 65535) {
walkSound = -1
}
runSound = buffer.readShort()
if (runSound == 65535) {
runSound = -1
}
soundDistance = buffer.readUnsignedByte()
}
135 -> {
primaryCursorOp = buffer.readUnsignedByte()
primaryCursor = buffer.readShort()
}
136 -> {
secondaryCursorOp = buffer.readUnsignedByte()
secondaryCursor = buffer.readShort()
}
137 -> attackCursor = buffer.readShort()
138 -> armyIcon = buffer.readShort()
139 -> spriteId = buffer.readShort()
140 -> ambientSoundVolume = buffer.readUnsignedByte()
141 -> visiblePriority = true
142 -> mapFunction = buffer.readShort()
143 -> invisiblePriority = true
in 150..154 -> {
options[opcode - 150] = buffer.readString()
if (!member) {
options[opcode - 150] = null
}
}
155 -> {
hue = buffer.readByte().toByte()
saturation = buffer.readByte().toByte()
lightness = buffer.readByte().toByte()
opacity = buffer.readByte().toByte()
}
158 -> mainOptionIndex = 1.toByte()
159 -> mainOptionIndex = 0.toByte()
160 -> {
val length = buffer.readUnsignedByte()
campaigns = IntArray(length)
repeat(length) { count ->
campaigns!![count] = buffer.readShort()
}
}
162 -> aBoolean2883 = true
163 -> anInt2803 = buffer.readUnsignedByte()
164 -> {
anInt2844 = buffer.readShort()
anInt2852 = buffer.readShort()
}
165 -> anInt2831 = buffer.readUnsignedByte()
168 -> anInt2862 = buffer.readUnsignedByte()
249 -> readParameters(buffer)
}
}
}

View file

@ -0,0 +1,228 @@
package cacheops.cache.definition.decoder
import cacheops.cache.Cache
import cacheops.cache.DefinitionDecoder
import cacheops.cache.buffer.read.Reader
import cacheops.cache.definition.data.ObjectDefinition
import const.Indices
open class ObjectDecoder(cache: Cache, val member: Boolean, val configReplace: Boolean) : DefinitionDecoder<ObjectDefinition>(cache, Indices.CONFIGURATION_OBJECT) {
override fun create() = ObjectDefinition()
override fun getFile(id: Int) = id and 0xff
override fun getArchive(id: Int) = id ushr 8
override fun readData(id: Int): ObjectDefinition? {
val def = super.readData(id)
val replacement = def?.getReplacementId() ?: return def
return super.readData(replacement)
}
private fun ObjectDefinition.getReplacementId(): Int? {
if (!configReplace) {
return null
}
val configIndex = 0
val configs = configObjectIds ?: return null
val config = if (configIndex < 0 || (configIndex >= configs.size - 1 || configs[configIndex] == -1)) {
configs[configs.size - 1]
} else {
configs.getOrNull(configIndex)
}
return if (config != -1) config else null
}
override fun ObjectDefinition.read(opcode: Int, buffer: Reader) {
when (opcode) {
1 -> {
val count = buffer.readUnsignedByte()
if (count > 0) {
if (modelIds == null) {
modelIds = IntArray(count)
modelTypes = IntArray(count)
var i = 0
while (count > i) {
modelIds!![i] = buffer.readUnsignedShort()
modelTypes!![i] = buffer.readUnsignedByte()
i++
}
} else {
buffer.position(buffer.position() + count * 3)
}
}
}
2 -> name = buffer.readString()
5 -> {
val i_30_ = buffer.readUnsignedByte()
if (i_30_ > 0) {
if (modelIds == null) {
modelIds = IntArray(i_30_)
modelTypes = null
var i_31_ = 0
while (i_30_ > i_31_) {
modelIds!![i_31_] = buffer.readUnsignedShort()
i_31_++
}
} else {
buffer.position(buffer.position() + i_30_ * 2)
}
}
}
14 -> sizeX = buffer.readUnsignedByte()
15 -> sizeY = buffer.readUnsignedByte()
17 -> {
blocksSky = false
solid = 0
}
18 -> blocksSky = false
19 -> interactive = buffer.readUnsignedByte()
21 -> contouredGround = 1
22 -> delayShading = true
23 -> culling = 1
24 -> {
val length = buffer.readUnsignedShort()
if (length != 65535) {
animations = intArrayOf(length)
}
}
27 -> solid = 1
28 -> offsetMultiplier = buffer.readUnsignedByte()
29 -> brightness = buffer.readByte()
in 30..34 -> options[opcode - 30] = buffer.readString()
39 -> contrast = buffer.readByte() * 5
40 -> readColours(buffer)
41 -> readTextures(buffer)
42 -> readColourPalette(buffer)
62 -> mirrored = true
64 -> castsShadow = false
65 -> modelSizeX = buffer.readUnsignedShort()
66 -> modelSizeZ = buffer.readUnsignedShort()
67 -> modelSizeY = buffer.readUnsignedShort()
69 -> blockFlag = buffer.readUnsignedByte()
70 -> offsetX = buffer.readUnsignedShort() shl 2
71 -> offsetZ = buffer.readUnsignedShort() shl 2
72 -> offsetY = buffer.readUnsignedShort() shl 2
73 -> blocksLand = true
74 -> ignoreOnRoute = true
75 -> supportItems = buffer.readUnsignedByte()
77, 92 -> {
varbitIndex = buffer.readUnsignedShort()
if (varbitIndex == 65535) {
varbitIndex = -1
}
configId = buffer.readUnsignedShort()
if (configId == 65535) {
configId = -1
}
var last = -1
if (opcode == 92) {
last = buffer.readUnsignedShort()
if (last == 65535) {
last = -1
}
}
val length = buffer.readUnsignedByte()
configObjectIds = IntArray(length + 2)
for (count in 0..length) {
configObjectIds!![count] = buffer.readUnsignedShort()
if (configObjectIds!![count] == 65535) {
configObjectIds!![count] = -1
}
}
configObjectIds!![length + 1] = last
}
78 -> {
anInt3015 = buffer.readUnsignedShort()
anInt3012 = buffer.readUnsignedByte()
}
79 -> {
anInt2989 = buffer.readUnsignedShort()
anInt2971 = buffer.readUnsignedShort()
anInt3012 = buffer.readUnsignedByte()
val length = buffer.readUnsignedByte()
anIntArray3036 = IntArray(length)
repeat(length) { count ->
anIntArray3036!![count] = buffer.readUnsignedShort()
}
}
81 -> {
contouredGround = 2.toByte()
anInt3023 = buffer.readUnsignedByte() * 256
}
82 -> hideMinimap = true
88 -> aBoolean2972 = false
89 -> animateImmediately = false
90 -> aBoolean1502 = true
91 -> isMembers = true
93 -> {
contouredGround = 3
anInt3023 = buffer.readUnsignedShort()
}
94 -> contouredGround = 4
95 -> {
contouredGround = 5
}
96 -> aBoolean1507 = true
97 -> adjustMapSceneRotation = true
98 -> hasAnimation = true
99 -> {
anInt2987 = buffer.readUnsignedByte()
anInt3008 = buffer.readUnsignedShort()
}
100 -> {
anInt3038 = buffer.readUnsignedByte()
anInt3013 = buffer.readUnsignedShort()
}
101 -> anInt2958 = buffer.readUnsignedByte()
102 -> mapscene = buffer.readUnsignedShort()
103 -> culling = 0
104 -> anInt3024 = buffer.readUnsignedByte()
105 -> invertMapScene = true
106 -> {
val length = buffer.readUnsignedByte()
var total = 0
animations = IntArray(length)
percents = IntArray(length)
repeat(length) { count ->
animations!![count] = buffer.readUnsignedShort()
if (animations!![count] == 65535) {
animations!![count] = -1
}
percents!![count] = buffer.readUnsignedByte()
total += percents!![count]
}
repeat(length) { count ->
percents!![count] = 65535 * percents!![count] / total
}
}
107 -> mapDefinitionId = buffer.readUnsignedShort()
in 150..154 -> {
options[-150 + opcode] = buffer.readString()
if (!member) {
options[-150 + opcode] = null
}
}
160 -> {
val length = buffer.readUnsignedByte()
anIntArray2981 = IntArray(length)
repeat(length) { count ->
anIntArray2981!![count] = buffer.readUnsignedShort()
}
}
249 -> readParameters(buffer)
}
}
companion object {
private fun skip(buffer: Reader) {
val length = buffer.readUnsignedByte()
repeat(length) {
buffer.skip(1)
val amount = buffer.readUnsignedByte()
buffer.skip(amount * 2)
}
}
}
}

View file

@ -0,0 +1,208 @@
package cacheops.cache.secure
import cacheops.cache.Cache
import cacheops.cache.buffer.read.Reader
import cacheops.cache.buffer.write.BufferWriter
class Huffman(cache: Cache) {
private var masks: IntArray? = null
private val frequencies: ByteArray
private var decryptKeys: IntArray
private val decryptedKeys: IntArray
private var decryptionValues = listOf(0, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1)
/**
* Load huffman tree from cache for compression
*/
init {
val huffman = cache.getFile(10, 1)!!
frequencies = huffman
masks = IntArray(huffman.size)
decryptKeys = IntArray(8)
val freq = IntArray(33)
var key = 0
//For each non-zero frequency
for ((index, size) in huffman.map { it.toInt() }.filter { it != 0 }.toIntArray().withIndex()) {
//Calculate maximum frequency
val maximumFreq = 1 shl 32 - size
//zero or the previous minimum
val currentFreq = freq[size]
//Store the min
masks!![index] = currentFreq
//Set the frequency to the
freq[size] = if (currentFreq and maximumFreq == 0) {//If the min and max are equal ish?
//Starting from the bottom find the smallest frequency indices
for (idx in size - 1 downTo 1) {
val leftFreq = freq[idx]
if (leftFreq != currentFreq) {
break
}
val rightFreq = 1 shl 32 - idx
if (rightFreq and leftFreq != 0) {
//Move up the tree?
freq[idx] = freq[idx - 1]
break
}
//Merge the two smallest trees
freq[idx] = leftFreq + rightFreq
}
//Sum of their frequencies
maximumFreq + currentFreq
} else {
//Move up the tree?
freq[size - 1]
}
for (idx in size + 1..32) {
if (currentFreq == freq[idx]) {
freq[idx] = freq[size]
}
}
var decryptIndex = 0
val value: Long = Int.MAX_VALUE + 1L
for(count in 0 until size) {
if (currentFreq and value.ushr(count).toInt() == 0) {
decryptIndex++
} else {
if (decryptKeys[decryptIndex] == 0) {
decryptKeys[decryptIndex] = key
}
decryptIndex = decryptKeys[decryptIndex]
}
if (decryptKeys.size <= decryptIndex) {
val keys = IntArray(decryptKeys.size * 2)
System.arraycopy(decryptKeys, 0, keys, 0, decryptKeys.size)
decryptKeys = keys
}
}
decryptKeys[decryptIndex] = index xor -0x1
if (key <= decryptIndex) {
key = 1 + decryptIndex
}
}
decryptedKeys = decryptKeys.map { it xor -0x1 }.toIntArray()
}
/**
* Decompresses string of length [characters] using Huffman coding
* @param packet The packet containing the compressed data
* @param characters The number of string characters to decompress
*/
fun decompress(packet: Reader, characters: Int): String {
val textBuffer = ByteArray(packet.readableBytes())
packet.readBytes(textBuffer)
return decompress(textBuffer, characters) ?: ""
}
fun decompress(message: ByteArray, length: Int): String? {
return try {
if(masks == null) {
return null
}
var charsDecoded = 0
var keyIndex = 0
val sb = StringBuilder()
chars@ for (character in message) {
for (value in decryptionValues) {
if (if (value == 0) character >= 0 else character.toInt() and value == 0) {
keyIndex++
} else {
keyIndex = decryptKeys[keyIndex]
}
val char = decryptedKeys[keyIndex]
if (char >= 0) {
sb.append(char.toChar())
if (length <= ++charsDecoded) {
break@chars
}
keyIndex = 0
}
}
}
sb.toString()
} catch (e: Throwable) {
e.printStackTrace()
null
}
}
/**
* Formats, compresses and writes [message] to [builder] using Huffman coding
* @param message The message to encode
* @param builder The packet to write the compressed data too
*/
fun compress(message: String, builder: BufferWriter) {
try {
//Format the message
val messageData = formatMessage(message)
//Write message length
builder.writeSmart(messageData.size)
//Write the compressed message
compress(messageData, builder)
} catch (exception: Throwable) {
exception.printStackTrace()
}
}
/**
* Compresses [message] using Huffman coding and writes to [builder]
* @param message The message to compress, split by symbol into a byte array
* @param builder The packet to write the compressed data too
*/
private fun compress(message: ByteArray, builder: BufferWriter) {
try {
if(masks == null) {
return
}
var key = 0
val startPosition = builder.position()
var position = startPosition shl 3
for (char in message) {
val character = char.toInt() and 0xff
val min = masks!![character]
val size = frequencies[character]
var offset = position shr 3
var bitOffset = position and 0x7
key = key and (-bitOffset shr 31)
position += size
val byteSize = (bitOffset + size - 1 shr 3) + offset
bitOffset += 24
key += min.ushr(bitOffset)
builder.setByte(offset, key)
while (offset < byteSize) {
bitOffset -= 8
key = min.ushr(bitOffset)
builder.setByte(++offset, key)
}
}
//Set the packet position to the correct place
builder.position(7 + position shr 3)
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* Replaces unknown symbols with question marks
* @param message The text to format
* @return message split by character
*/
private fun formatMessage(message: String): ByteArray {
val array = ByteArray(message.length)
for ((index, c) in message.withIndex()) {
val char = c.code
array[index] = if (char <= 0 || (char in 128..159) || char > 255) {
63.toByte()
} else {
char.toByte()
}
}
return array
}
}

View file

@ -0,0 +1,56 @@
package cacheops.cache.secure
import java.math.BigInteger
import java.nio.ByteBuffer
import java.security.SecureRandom
object RSA {
/**
* Encrypt/decrypts bytes with key and modulus
*/
fun crypt(data: ByteArray, modulus: BigInteger, key: BigInteger): ByteArray {
return BigInteger(data).modPow(key, modulus).toByteArray()
}
/**
* Encrypt/decrypts [ByteBuffer] with key and modulus
*/
fun crypt(data: ByteBuffer, modulus: BigInteger, key: BigInteger): ByteBuffer {
return ByteBuffer.wrap(BigInteger(data.array()).modPow(key, modulus).toByteArray())
}
@JvmStatic
fun main(args: Array<String>) {
generateRsa()
}
/**
* Generates rsa values
*/
private fun generateRsa() {
val bits = 1024
val random = SecureRandom()
var p: BigInteger
var q: BigInteger
var phi: BigInteger
var modulus: BigInteger
var publicKey: BigInteger
var privateKey: BigInteger
do {
p = BigInteger.probablePrime(bits / 2, random)
q = BigInteger.probablePrime(bits / 2, random)
phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE))
modulus = p.multiply(q)
publicKey = BigInteger("65537")
privateKey = publicKey.modInverse(phi)
} while (modulus.bitLength() != bits || privateKey.bitLength() != bits || phi.gcd(publicKey) != BigInteger.ONE)
println("modulus: ${modulus.toString(16)}")
println("public key: ${publicKey.toString(16)}")
println("private key: ${privateKey.toString(16)}")
}
}

View file

@ -0,0 +1,77 @@
package cacheops.cache.secure
import java.nio.ByteBuffer
object Xtea {
/**
* The golden ratio.
*/
private const val GOLDEN_RATIO = -0x61c88647
/**
* The number of rounds.
*/
private const val ROUNDS = 32
/**
* Deciphers the specified [ByteBuffer] with the given key.
* @param buffer The buffer.
* @param key The key.
* @throws IllegalArgumentException if the key is not exactly 4 elements
* long.
*/
fun decipher(buffer: ByteArray, key: IntArray, start: Int = 0) {
if (key.size != 4) {
throw IllegalArgumentException()
}
val numQuads = buffer.size / 8
for (i in 0 until numQuads) {
var sum = GOLDEN_RATIO * ROUNDS
var v0 = getInt(buffer, start + i * 8)
var v1 = getInt(buffer, start + i * 8 + 4)
for (j in 0 until ROUNDS) {
v1 -= (v0 shl 4 xor v0.ushr(5)) + v0 xor sum + key[sum.ushr(11) and 3]
sum -= GOLDEN_RATIO
v0 -= (v1 shl 4 xor v1.ushr(5)) + v1 xor sum + key[sum and 3]
}
putInt(buffer, start + i * 8, v0)
putInt(buffer, start + i * 8 + 4, v1)
}
}
/**
* Enciphers the specified [ByteArray] with the given key.
* @param buffer The buffer.
* @param key The key.
* @throws IllegalArgumentException if the key is not exactly 4 elements
* long.
*/
fun encipher(buffer: ByteArray, start: Int, end: Int, key: IntArray) {
if (key.size != 4)
throw IllegalArgumentException()
val numQuads = (end - start) / 8
for (i in 0 until numQuads) {
var sum = 0
var v0 = getInt(buffer, start + i * 8)
var v1 = getInt(buffer, start + i * 8 + 4)
for (j in 0 until ROUNDS) {
v0 += (v1 shl 4 xor v1.ushr(5)) + v1 xor sum + key[sum and 3]
sum += GOLDEN_RATIO
v1 += (v0 shl 4 xor v0.ushr(5)) + v0 xor sum + key[sum.ushr(11) and 3]
}
putInt(buffer, start + i * 8, v0)
putInt(buffer, start + i * 8 + 4, v1)
}
}
private fun getInt(buffer: ByteArray, index: Int) = (buffer[index].toInt() and 0xff shl 24) or (buffer[index + 1].toInt() and 0xff shl 16) or (buffer[index + 2].toInt() and 0xff shl 8) or (buffer[index + 3].toInt() and 0xff)
private fun putInt(buffer: ByteArray, index: Int, value: Int) {
buffer[index] = (value shr 24).toByte()
buffer[index + 1] = (value shr 16).toByte()
buffer[index + 2] = (value shr 8).toByte()
buffer[index + 3] = value.toByte()
}
}