Skip to content

Commit

Permalink
feat: remaining packets (excluding reflection checker and npc infos)
Browse files Browse the repository at this point in the history
  • Loading branch information
Z-Kris committed Apr 12, 2024
1 parent f17a80c commit 72dd6e5
Show file tree
Hide file tree
Showing 10 changed files with 445 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package net.rsprot.protocol.game.outgoing.codec.misc.client

import io.netty.channel.ChannelHandlerContext
import net.rsprot.buffer.JagByteBuf
import net.rsprot.protocol.ServerProt
import net.rsprot.protocol.game.outgoing.misc.client.HiscoreReply
import net.rsprot.protocol.game.outgoing.prot.GameServerProt
import net.rsprot.protocol.message.codec.MessageEncoder
import net.rsprot.protocol.metadata.Consistent

@Consistent
public class HiscoreReplyEncoder : MessageEncoder<HiscoreReply> {
override val prot: ServerProt = GameServerProt.HISCORE_REPLY

override fun encode(
ctx: ChannelHandlerContext,
buffer: JagByteBuf,
message: HiscoreReply,
) {
buffer.p1(message.requestId)
when (val response = message.response) {
is HiscoreReply.FailedHiscoreReply -> {
buffer.p1(1)
buffer.pjstr(response.reason)
}
is HiscoreReply.SuccessfulHiscoreReply -> {
buffer.p1(0)
buffer.p1(response.statResults.size)
for (stat in response.statResults) {
buffer.p2(stat.id)
buffer.p4(stat.rank)
buffer.p4(stat.result)
}
buffer.p4(response.overallRank)
buffer.p8(response.overallExperience)
buffer.p2(response.activityResults.size)
for (activity in response.activityResults) {
buffer.p2(activity.id)
buffer.p4(activity.rank)
buffer.p4(activity.result)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.rsprot.protocol.game.outgoing.codec.misc.client

import io.netty.channel.ChannelHandlerContext
import net.rsprot.buffer.JagByteBuf
import net.rsprot.protocol.ServerProt
import net.rsprot.protocol.game.outgoing.misc.client.SendPing
import net.rsprot.protocol.game.outgoing.prot.GameServerProt
import net.rsprot.protocol.message.codec.MessageEncoder
import net.rsprot.protocol.metadata.Consistent

@Consistent
public class SendPingEncoder : MessageEncoder<SendPing> {
override val prot: ServerProt = GameServerProt.SEND_PING

override fun encode(
ctx: ChannelHandlerContext,
buffer: JagByteBuf,
message: SendPing,
) {
buffer.p4(message.value1)
buffer.p4(message.value2)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package net.rsprot.protocol.game.outgoing.codec.misc.client

import io.netty.channel.ChannelHandlerContext
import net.rsprot.buffer.JagByteBuf
import net.rsprot.protocol.ServerProt
import net.rsprot.protocol.game.outgoing.misc.client.UpdateSiteSettings
import net.rsprot.protocol.game.outgoing.prot.GameServerProt
import net.rsprot.protocol.message.codec.MessageEncoder
import net.rsprot.protocol.metadata.Consistent

@Consistent
public class UpdateSiteSettingsEncoder : MessageEncoder<UpdateSiteSettings> {
override val prot: ServerProt = GameServerProt.UPDATE_SITESETTINGS

override fun encode(
ctx: ChannelHandlerContext,
buffer: JagByteBuf,
message: UpdateSiteSettings,
) {
buffer.pjstr(message.settings)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package net.rsprot.protocol.game.outgoing.codec.misc.client

import io.netty.channel.ChannelHandlerContext
import net.rsprot.buffer.JagByteBuf
import net.rsprot.crypto.crc.CyclicRedundancyCheck
import net.rsprot.protocol.ServerProt
import net.rsprot.protocol.game.outgoing.misc.client.UpdateUid192
import net.rsprot.protocol.game.outgoing.prot.GameServerProt
import net.rsprot.protocol.message.codec.MessageEncoder
import net.rsprot.protocol.metadata.Consistent

@Consistent
public class UpdateUid192Encoder : MessageEncoder<UpdateUid192> {
override val prot: ServerProt = GameServerProt.UPDATE_UID192

override fun encode(
ctx: ChannelHandlerContext,
buffer: JagByteBuf,
message: UpdateUid192,
) {
buffer.pdata(message.uid)
buffer.p4(CyclicRedundancyCheck.computeCrc32(message.uid))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package net.rsprot.protocol.game.outgoing.codec.misc.client

import io.netty.channel.ChannelHandlerContext
import net.rsprot.buffer.JagByteBuf
import net.rsprot.protocol.ServerProt
import net.rsprot.protocol.channel.ChannelAttributes
import net.rsprot.protocol.game.outgoing.misc.client.UrlOpen
import net.rsprot.protocol.game.outgoing.prot.GameServerProt
import net.rsprot.protocol.message.codec.MessageEncoder
import net.rsprot.protocol.metadata.Consistent

@Consistent
public class UrlOpenEncoder : MessageEncoder<UrlOpen> {
override val prot: ServerProt = GameServerProt.URL_OPEN

override fun encode(
ctx: ChannelHandlerContext,
buffer: JagByteBuf,
message: UrlOpen,
) {
val cipherPair =
ctx.channel().attr(ChannelAttributes.STREAM_CIPHER_PAIR).get()
?: throw IllegalStateException("Stream cipher not initialized.")
val encoderCipher = cipherPair.encoderCipher
val marker = buffer.writerIndex()
buffer.pjstr(message.url)

// Encrypt the entire buffer with a stream cipher
for (i in marker..<buffer.writerIndex()) {
buffer.buffer.setByte(i, buffer.buffer.getByte(i) + encoderCipher.nextInt())
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package net.rsprot.protocol.game.outgoing.misc.client

import net.rsprot.protocol.message.OutgoingMessage

/**
* Hiscore reply is a packet used in the enhanced clients to do
* lookups of nearby players, to find out their stats and rankings
* on the high scores.
* This packet is sent as a response to the hiscore request packet.
* @property requestId the id of the request that was made.
* @property response the response to be written to the client.
*/
public class HiscoreReply private constructor(
private val _requestId: UByte,
public val response: HiscoreReplyResponse,
) : OutgoingMessage {
public constructor(
requestId: Int,
response: HiscoreReplyResponse,
) : this(
requestId.toUByte(),
response,
)

public val requestId: Int
get() = _requestId.toInt()

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as HiscoreReply

if (_requestId != other._requestId) return false
if (response != other.response) return false

return true
}

override fun hashCode(): Int {
var result = _requestId.hashCode()
result = 31 * result + response.hashCode()
return result
}

override fun toString(): String {
return "HiscoreReply(" +
"requestId=$requestId, " +
"response=$response" +
")"
}

public sealed interface HiscoreReplyResponse

/**
* A successful hiscore reply, transmitting all the stat and activity results.
* It is worth noting that because the packet isn't used, it is not entirely
* certain that the naming of these properties is accurate. These are merely
* a guess based on the hiscore json syntax.
* @property statResults the list of stats to transmit
* @property overallRank the overall rank of this player based on the total level
* @property overallExperience the overall experience of this player
* @property activityResults the list of activity results to transmit.
*/
public class SuccessfulHiscoreReply(
public val statResults: List<HiscoreResult>,
public val overallRank: Int,
public val overallExperience: Long,
public val activityResults: List<HiscoreResult>,
) : HiscoreReplyResponse {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as SuccessfulHiscoreReply

if (statResults != other.statResults) return false
if (overallRank != other.overallRank) return false
if (overallExperience != other.overallExperience) return false
if (activityResults != other.activityResults) return false

return true
}

override fun hashCode(): Int {
var result = statResults.hashCode()
result = 31 * result + overallRank
result = 31 * result + overallExperience.hashCode()
result = 31 * result + activityResults.hashCode()
return result
}

override fun toString(): String {
return "SuccessfulHiscoreReply(" +
"statResults=$statResults, " +
"overallRank=$overallRank, " +
"overallExperience=$overallExperience, " +
"activityResults=$activityResults" +
")"
}
}

/**
* A failed hiscore reply would be sent when a lookup could not be
* performed successfully. The client will read a string for a reason
* when this occurs.
* @property reason the reason to give to the player for why
* the lookup could not be done.
*/
public class FailedHiscoreReply(
public val reason: String,
) : HiscoreReplyResponse {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as FailedHiscoreReply

return reason == other.reason
}

override fun hashCode(): Int {
return reason.hashCode()
}

override fun toString(): String {
return "FailedHiscoreReply(reason='$reason')"
}
}

public class HiscoreResult(
public val id: Int,
public val rank: Int,
public val result: Int,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as HiscoreResult

if (id != other.id) return false
if (rank != other.rank) return false
if (result != other.result) return false

return true
}

override fun hashCode(): Int {
var result1 = id
result1 = 31 * result1 + rank
result1 = 31 * result1 + result
return result1
}

override fun toString(): String {
return "HiscoreResult(" +
"id=$id, " +
"rank=$rank, " +
"result=$result" +
")"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package net.rsprot.protocol.game.outgoing.misc.client

import net.rsprot.protocol.message.OutgoingMessage

/**
* Send ping packet is used to request a ping response from the client.
* The client will send these [value1] and [value2] variables back to the
* server in exchange.
* These integer identifiers do not appear to have any known structure to
* them - they are not epoch time in any form. Seemingly random as the value
* can change drastically between different logins.
* @property value1 the first 32-bit integer identifier.
* @property value2 the second 32-bit integer identifier.
*/
public class SendPing(
public val value1: Int,
public val value2: Int,
) : OutgoingMessage {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as SendPing

if (value1 != other.value1) return false
if (value2 != other.value2) return false

return true
}

override fun hashCode(): Int {
var result = value1
result = 31 * result + value2
return result
}

override fun toString(): String {
return "SendPing(" +
"value1=$value1, " +
"value2=$value2" +
")"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.rsprot.protocol.game.outgoing.misc.client

import net.rsprot.protocol.message.OutgoingMessage

/**
* Update site settings packet is used to identify the given client.
* The settings are sent as part of the URL when connecting to services
* or secure RuneScape URLs.
* @property settings the settings string to assign
*/
public class UpdateSiteSettings(
public val settings: String,
) : OutgoingMessage {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as UpdateSiteSettings

return settings == other.settings
}

override fun hashCode(): Int {
return settings.hashCode()
}

override fun toString(): String {
return "UpdateSiteSettings(settings='$settings')"
}
}
Loading

0 comments on commit 72dd6e5

Please sign in to comment.