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

149 lines
3.8 KiB

package org.openrs2.buffer
import com.google.common.base.Preconditions
import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufUtil
import io.netty.buffer.Unpooled
import io.netty.util.ByteProcessor
import org.openrs2.util.charset.Cp1252Charset
import java.nio.charset.Charset
import java.util.zip.CRC32
private const val STRING_VERSION = 0
public fun wrappedBuffer(vararg bytes: Byte): ByteBuf {
return Unpooled.wrappedBuffer(bytes)
}
public fun copiedBuffer(s: String, charset: Charset = Charsets.UTF_8): ByteBuf {
return Unpooled.copiedBuffer(s, charset)
}
public fun ByteBuf.readShortSmart(): Int {
val peek = getUnsignedByte(readerIndex()).toInt()
return if ((peek and 0x80) == 0) {
readUnsignedByte().toInt() - 0x40
} else {
(readUnsignedShort() and 0x7FFF) - 0x4000
}
}
public fun ByteBuf.writeShortSmart(v: Int): ByteBuf {
when (v) {
in -0x40..0x3F -> writeByte(v + 0x40)
in -0x4000..0x3FFF -> writeShort(0x8000 or (v + 0x4000))
else -> throw IllegalArgumentException()
}
return this
}
public fun ByteBuf.readUnsignedShortSmart(): Int {
val peek = getUnsignedByte(readerIndex()).toInt()
return if ((peek and 0x80) == 0) {
readUnsignedByte().toInt()
} else {
readUnsignedShort() and 0x7FFF
}
}
public fun ByteBuf.writeUnsignedShortSmart(v: Int): ByteBuf {
when (v) {
in 0..0x7F -> writeByte(v)
in 0..0x7FFF -> writeShort(0x8000 or v)
else -> throw IllegalArgumentException()
}
return this
}
public fun ByteBuf.readIntSmart(): Int {
val peek = getUnsignedByte(readerIndex()).toInt()
return if ((peek and 0x80) == 0) {
readUnsignedShort() - 0x4000
} else {
(readInt() and 0x7FFFFFFF) - 0x40000000
}
}
public fun ByteBuf.writeIntSmart(v: Int): ByteBuf {
when (v) {
in -0x4000..0x3FFF -> writeShort(v + 0x4000)
in -0x40000000..0x3FFFFFFF -> writeInt(0x80000000.toInt() or (v + 0x40000000))
else -> throw IllegalArgumentException()
}
return this
}
public fun ByteBuf.readUnsignedIntSmart(): Int {
val peek = getUnsignedByte(readerIndex()).toInt()
return if ((peek and 0x80) == 0) {
readUnsignedShort()
} else {
readInt() and 0x7FFFFFFF
}
}
public fun ByteBuf.writeUnsignedIntSmart(v: Int): ByteBuf {
when (v) {
in 0..0x7FFF -> writeShort(v)
in 0..0x7FFFFFFF -> writeInt(0x80000000.toInt() or v)
else -> throw IllegalArgumentException()
}
return this
}
public fun ByteBuf.readString(): String {
val start = readerIndex()
val end = forEachByte(ByteProcessor.FIND_NUL)
require(end != -1) {
"Unterminated string"
}
val s = toString(start, end - start, Cp1252Charset)
readerIndex(end + 1)
return s
}
public fun ByteBuf.writeString(s: CharSequence): ByteBuf {
writeCharSequence(s, Cp1252Charset)
writeByte(0)
return this
}
public fun ByteBuf.readVersionedString(): String {
val version = readUnsignedByte().toInt()
require(version == STRING_VERSION) {
"Unsupported version number $version"
}
return readString()
}
public fun ByteBuf.writeVersionedString(s: CharSequence): ByteBuf {
writeByte(STRING_VERSION)
writeString(s)
return this
}
public fun ByteBuf.crc32(): Int {
return crc32(readerIndex(), readableBytes())
}
public fun ByteBuf.crc32(index: Int, len: Int): Int {
Preconditions.checkPositionIndexes(index, index + len, capacity())
val crc = CRC32()
val count = nioBufferCount()
when {
hasArray() -> crc.update(array(), arrayOffset() + index, len)
count > 1 -> nioBuffers(index, len).forEach(crc::update)
count == 1 -> crc.update(nioBuffer(index, len))
else -> crc.update(ByteBufUtil.getBytes(this, index, len, false))
}
return crc.value.toInt()
}