-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: zone packets (excluding partial enclosed, as need to figure out the design of that first) * chore: create an osrs-221-api module that will be the 'root' to bringing the entire application together from the server's perspective * refactor: move ZoneProt and ZoneProtEncoder to revision-specific internal modules * feat: UpdateZonePartialEnclosed initial implementation, subject to change if a better design gets figured out * feat: update dictionary with new entries
- Loading branch information
Showing
36 changed files
with
2,115 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
plugins { | ||
alias(libs.plugins.kotlin.jvm) | ||
} | ||
|
||
dependencies { | ||
api(libs.netty.buffer) | ||
api(projects.protocol) | ||
api(projects.compression) | ||
api(projects.crypto) | ||
api(projects.protocol.osrs221Shared) | ||
api(projects.protocol.osrs221Model) | ||
implementation(projects.protocol.osrs221Internal) | ||
implementation(projects.protocol.osrs221Desktop) | ||
} |
153 changes: 153 additions & 0 deletions
153
...sprot/protocol/game/outgoing/codec/zone/header/DesktopUpdateZonePartialEnclosedEncoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
package net.rsprot.protocol.game.outgoing.codec.zone.header | ||
|
||
import io.netty.buffer.ByteBuf | ||
import io.netty.buffer.ByteBufAllocator | ||
import io.netty.channel.ChannelHandlerContext | ||
import net.rsprot.buffer.JagByteBuf | ||
import net.rsprot.buffer.extensions.toJagByteBuf | ||
import net.rsprot.protocol.ServerProt | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.LocAddChangeEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.LocAnimEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.LocDelEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.LocMergeEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.MapAnimEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.MapProjAnimEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.ObjAddEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.ObjCountEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.ObjDelEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.ObjOpFilterEncoder | ||
import net.rsprot.protocol.game.outgoing.codec.zone.payload.SoundAreaEncoder | ||
import net.rsprot.protocol.game.outgoing.prot.GameServerProt | ||
import net.rsprot.protocol.game.outgoing.zone.header.UpdateZonePartialEnclosed | ||
import net.rsprot.protocol.internal.game.outgoing.codec.zone.payload.ZoneProt | ||
import net.rsprot.protocol.internal.game.outgoing.codec.zone.payload.ZoneProtEncoder | ||
import net.rsprot.protocol.message.codec.MessageEncoder | ||
import kotlin.math.min | ||
|
||
public class DesktopUpdateZonePartialEnclosedEncoder : MessageEncoder<UpdateZonePartialEnclosed> { | ||
override val prot: ServerProt = GameServerProt.UPDATE_ZONE_PARTIAL_ENCLOSED | ||
|
||
override fun encode( | ||
ctx: ChannelHandlerContext, | ||
buffer: JagByteBuf, | ||
message: UpdateZonePartialEnclosed, | ||
) { | ||
buffer.p1(message.zoneX) | ||
buffer.p1Alt2(message.zoneZ) | ||
buffer.p1Alt3(message.level) | ||
buffer.buffer.writeBytes( | ||
message.payload, | ||
message.payload.readerIndex(), | ||
message.payload.readableBytes(), | ||
) | ||
} | ||
|
||
public companion object { | ||
private const val MAX_PARTIAL_ENCLOSED_SIZE = 40_000 - 3 | ||
|
||
/** | ||
* Builds a cache of a given zone's list of zone prots. | ||
* This is intended so the server only requests one cache per zone per game cycle, | ||
* rather than re-building the same buffer N times, where N is the number of players | ||
* observing the zone. With this in mind however, zone prots which are player-specific, | ||
* such as OBJ_ADD cannot be grouped together and must be sent separately, as they also | ||
* are in OldSchool RuneScape. | ||
* @param allocator the byte buffer allocator used for the cached buffer. | ||
* Note that it is the server's responsibility to release the buffer once the cycle has ended. | ||
* The individual writes of [UpdateZonePartialEnclosed] do not modify the reference count | ||
* in any way. | ||
* @param messages the list of zone prot messages to be encoded. | ||
*/ | ||
public fun buildCache( | ||
allocator: ByteBufAllocator, | ||
messages: List<ZoneProt>, | ||
): ByteBuf { | ||
val buffer = | ||
allocator.buffer( | ||
min(IndexedZoneProtEncoder.maxZoneProtSize * messages.size, MAX_PARTIAL_ENCLOSED_SIZE), | ||
MAX_PARTIAL_ENCLOSED_SIZE, | ||
).toJagByteBuf() | ||
for (message in messages) { | ||
val indexedEncoder = IndexedZoneProtEncoder.indexedEncoders[message.protId] | ||
buffer.p1(indexedEncoder.ordinal) | ||
encodeMessage( | ||
buffer, | ||
message, | ||
indexedEncoder.encoder, | ||
) | ||
} | ||
return buffer.buffer | ||
} | ||
|
||
/** | ||
* Encodes the [message] into the [buffer] using the [encoder] as the encoder for it. | ||
* @param buffer the buffer to encode into | ||
* @param message the message to be encoded | ||
* @param encoder the encoder to use for encoding the message. | ||
* Note that the type of the encoder is not compile-time known as we acquire it dynamically | ||
* based on the message itself. | ||
*/ | ||
private fun <T : ZoneProt> encodeMessage( | ||
buffer: JagByteBuf, | ||
message: T, | ||
encoder: ZoneProtEncoder<*>, | ||
) { | ||
@Suppress("UNCHECKED_CAST") | ||
encoder as ZoneProtEncoder<T> | ||
encoder.encode(buffer, message) | ||
} | ||
|
||
/** | ||
* Zone prot encoders here are used specifically by the [UpdateZonePartialEnclosed] | ||
* packet, as this packet has its own sub-system of the zone prots, with the ability | ||
* to send a batch of zone packets in one go with its own internal indexing. | ||
* | ||
* WARNING: This enum's order MUST match the order in the client, as the | ||
* [IndexedZoneProtEncoder.ordinal] function is used for indexing! | ||
* | ||
* @property protId the respective [ZoneProt.protId] of each message, used for | ||
* quick indexing of respective messages. | ||
* @property encoder the zone prot encoder responsible for encoding the respective message | ||
* into a byte buffer. | ||
*/ | ||
private enum class IndexedZoneProtEncoder( | ||
private val protId: Int, | ||
val encoder: ZoneProtEncoder<*>, | ||
) { | ||
LOC_DEL(ZoneProt.LOC_DEL, LocDelEncoder()), | ||
OBJ_DEL(ZoneProt.OBJ_DEL, ObjDelEncoder()), | ||
LOC_ANIM(ZoneProt.LOC_ANIM, LocAnimEncoder()), | ||
LOC_MERGE(ZoneProt.LOC_MERGE, LocMergeEncoder()), | ||
OBJ_ADD(ZoneProt.OBJ_ADD, ObjAddEncoder()), | ||
MAP_ANIM(ZoneProt.MAP_ANIM, MapAnimEncoder()), | ||
OBJ_COUNT(ZoneProt.OBJ_COUNT, ObjCountEncoder()), | ||
OBJ_OPFILTER(ZoneProt.OBJ_OPFILTER, ObjOpFilterEncoder()), | ||
MAP_PROJANIM(ZoneProt.MAP_PROJANIM, MapProjAnimEncoder()), | ||
SOUND_AREA(ZoneProt.SOUND_AREA, SoundAreaEncoder()), | ||
LOC_ADD_CHANGE(ZoneProt.LOC_ADD_CHANGE, LocAddChangeEncoder()), | ||
; | ||
|
||
companion object { | ||
/** | ||
* The maximum possible size of a single zone prot. | ||
* This constant is used to determine the maximum initial possible buffer capacity. | ||
*/ | ||
val maxZoneProtSize = | ||
entries.maxOf { | ||
it.encoder.prot.size | ||
} | ||
|
||
/** | ||
* The zone prot encoders indexed by their prot ids, allowing for fast access based | ||
* on the respective [ZoneProt.protId] through the array. | ||
*/ | ||
val indexedEncoders = | ||
Array(entries.size) { index -> | ||
entries.first { prot -> | ||
index == prot.protId | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
...otlin/net/rsprot/protocol/game/outgoing/codec/zone/header/UpdateZoneFullFollowsEncoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package net.rsprot.protocol.game.outgoing.codec.zone.header | ||
|
||
import io.netty.channel.ChannelHandlerContext | ||
import net.rsprot.buffer.JagByteBuf | ||
import net.rsprot.protocol.ServerProt | ||
import net.rsprot.protocol.game.outgoing.prot.GameServerProt | ||
import net.rsprot.protocol.game.outgoing.zone.header.UpdateZoneFullFollows | ||
import net.rsprot.protocol.message.codec.MessageEncoder | ||
|
||
public class UpdateZoneFullFollowsEncoder : MessageEncoder<UpdateZoneFullFollows> { | ||
override val prot: ServerProt = GameServerProt.UPDATE_ZONE_FULL_FOLLOWS | ||
|
||
override fun encode( | ||
ctx: ChannelHandlerContext, | ||
buffer: JagByteBuf, | ||
message: UpdateZoneFullFollows, | ||
) { | ||
buffer.p1(message.zoneZ) | ||
buffer.p1(message.level) | ||
buffer.p1Alt1(message.zoneX) | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
...in/net/rsprot/protocol/game/outgoing/codec/zone/header/UpdateZonePartialFollowsEncoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package net.rsprot.protocol.game.outgoing.codec.zone.header | ||
|
||
import io.netty.channel.ChannelHandlerContext | ||
import net.rsprot.buffer.JagByteBuf | ||
import net.rsprot.protocol.ServerProt | ||
import net.rsprot.protocol.game.outgoing.prot.GameServerProt | ||
import net.rsprot.protocol.game.outgoing.zone.header.UpdateZonePartialFollows | ||
import net.rsprot.protocol.message.codec.MessageEncoder | ||
|
||
public class UpdateZonePartialFollowsEncoder : MessageEncoder<UpdateZonePartialFollows> { | ||
override val prot: ServerProt = GameServerProt.UPDATE_ZONE_PARTIAL_FOLLOWS | ||
|
||
override fun encode( | ||
ctx: ChannelHandlerContext, | ||
buffer: JagByteBuf, | ||
message: UpdateZonePartialFollows, | ||
) { | ||
buffer.p1Alt3(message.zoneX) | ||
buffer.p1(message.zoneZ) | ||
buffer.p1Alt3(message.level) | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
...c/main/kotlin/net/rsprot/protocol/game/outgoing/codec/zone/payload/LocAddChangeEncoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package net.rsprot.protocol.game.outgoing.codec.zone.payload | ||
|
||
import net.rsprot.buffer.JagByteBuf | ||
import net.rsprot.protocol.ServerProt | ||
import net.rsprot.protocol.game.outgoing.prot.GameServerProt | ||
import net.rsprot.protocol.game.outgoing.zone.payload.LocAddChange | ||
import net.rsprot.protocol.internal.game.outgoing.codec.zone.payload.ZoneProtEncoder | ||
|
||
public class LocAddChangeEncoder : ZoneProtEncoder<LocAddChange> { | ||
override val prot: ServerProt = GameServerProt.LOC_ADD_CHANGE | ||
|
||
override fun encode( | ||
buffer: JagByteBuf, | ||
message: LocAddChange, | ||
) { | ||
// The function at the bottom of the LOC_ADD_CHANGE has a consistent order, | ||
// making it easy to identify all the properties of this packet: | ||
// loc_add_change_del(level, x, z, layer, id, shape, rotation, opFlags, 0, -1) | ||
buffer.p2Alt2(message.id) | ||
buffer.p1Alt1(message.coordInZonePacked) | ||
buffer.p1Alt3(message.locPropertiesPacked) | ||
buffer.p1Alt3(message.opFlags.value) | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
...op/src/main/kotlin/net/rsprot/protocol/game/outgoing/codec/zone/payload/LocAnimEncoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package net.rsprot.protocol.game.outgoing.codec.zone.payload | ||
|
||
import net.rsprot.buffer.JagByteBuf | ||
import net.rsprot.protocol.ServerProt | ||
import net.rsprot.protocol.game.outgoing.prot.GameServerProt | ||
import net.rsprot.protocol.game.outgoing.zone.payload.LocAnim | ||
import net.rsprot.protocol.internal.game.outgoing.codec.zone.payload.ZoneProtEncoder | ||
|
||
public class LocAnimEncoder : ZoneProtEncoder<LocAnim> { | ||
override val prot: ServerProt = GameServerProt.LOC_ANIM | ||
|
||
override fun encode( | ||
buffer: JagByteBuf, | ||
message: LocAnim, | ||
) { | ||
// The function at the bottom of the LOC_ANIM has a consistent order, | ||
// making it easy to identify all the properties of this packet: | ||
// loc_anim(level, x, z, shape, rotation, layer, id) | ||
buffer.p2Alt2(message.id) | ||
buffer.p1(message.locPropertiesPacked) | ||
buffer.p1Alt3(message.coordInZonePacked) | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
...top/src/main/kotlin/net/rsprot/protocol/game/outgoing/codec/zone/payload/LocDelEncoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package net.rsprot.protocol.game.outgoing.codec.zone.payload | ||
|
||
import net.rsprot.buffer.JagByteBuf | ||
import net.rsprot.protocol.ServerProt | ||
import net.rsprot.protocol.game.outgoing.prot.GameServerProt | ||
import net.rsprot.protocol.game.outgoing.zone.payload.LocDel | ||
import net.rsprot.protocol.internal.game.outgoing.codec.zone.payload.ZoneProtEncoder | ||
|
||
public class LocDelEncoder : ZoneProtEncoder<LocDel> { | ||
override val prot: ServerProt = GameServerProt.LOC_DEL | ||
|
||
override fun encode( | ||
buffer: JagByteBuf, | ||
message: LocDel, | ||
) { | ||
// The function at the bottom of the LOC_DEL has a consistent order, | ||
// making it easy to identify all the properties of this packet: | ||
// loc_add_change_del(level, x, z, layer, -1, shape, rotation, 31, 0, -1) | ||
buffer.p1Alt3(message.coordInZonePacked) | ||
buffer.p1Alt3(message.locPropertiesPacked) | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
...p/src/main/kotlin/net/rsprot/protocol/game/outgoing/codec/zone/payload/LocMergeEncoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package net.rsprot.protocol.game.outgoing.codec.zone.payload | ||
|
||
import net.rsprot.buffer.JagByteBuf | ||
import net.rsprot.protocol.ServerProt | ||
import net.rsprot.protocol.game.outgoing.prot.GameServerProt | ||
import net.rsprot.protocol.game.outgoing.zone.payload.LocMerge | ||
import net.rsprot.protocol.internal.game.outgoing.codec.zone.payload.ZoneProtEncoder | ||
|
||
public class LocMergeEncoder : ZoneProtEncoder<LocMerge> { | ||
override val prot: ServerProt = GameServerProt.LOC_MERGE | ||
|
||
override fun encode( | ||
buffer: JagByteBuf, | ||
message: LocMerge, | ||
) { | ||
// The function at the bottom of the LOC_MERGE has a consistent order, | ||
// making it easy to identify all the properties of this packet: | ||
// loc_merge(level, x, z, shape, rotation, layer, id, start, end, minX, minZ, maxX, maxZ, player) | ||
buffer.p1Alt3(message.minX) | ||
buffer.p1Alt3(message.minZ) | ||
buffer.p2Alt2(message.index) | ||
buffer.p2(message.id) | ||
buffer.p1Alt2(message.locPropertiesPacked) | ||
buffer.p1Alt3(message.maxX) | ||
buffer.p2Alt1(message.start) | ||
buffer.p2Alt1(message.end) | ||
buffer.p1(message.coordInZonePacked) | ||
buffer.p1Alt2(message.maxZ) | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
...op/src/main/kotlin/net/rsprot/protocol/game/outgoing/codec/zone/payload/MapAnimEncoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package net.rsprot.protocol.game.outgoing.codec.zone.payload | ||
|
||
import net.rsprot.buffer.JagByteBuf | ||
import net.rsprot.protocol.ServerProt | ||
import net.rsprot.protocol.game.outgoing.prot.GameServerProt | ||
import net.rsprot.protocol.game.outgoing.zone.payload.MapAnim | ||
import net.rsprot.protocol.internal.game.outgoing.codec.zone.payload.ZoneProtEncoder | ||
|
||
public class MapAnimEncoder : ZoneProtEncoder<MapAnim> { | ||
override val prot: ServerProt = GameServerProt.MAP_ANIM | ||
|
||
override fun encode( | ||
buffer: JagByteBuf, | ||
message: MapAnim, | ||
) { | ||
// While MAP_ANIM does not have a common function like the rest, | ||
// the constructor for the SpotAnimation object itself has the following order: | ||
// SpotAnimation(id, level, fineX, fineZ, getGroundHeight(fineX, fineZ, level) - height, delay, cycle) | ||
buffer.p1Alt1(message.coordInZonePacked) | ||
buffer.p2Alt1(message.delay) | ||
buffer.p2(message.id) | ||
buffer.p1Alt1(message.height) | ||
} | ||
} |
Oops, something went wrong.