packets.clj
Branches > main > 28220a7 > files / src / net / bowmap / transport / packets.clj
(ns net.bowmap.transport.packets
(:require
[net.bowmap.protocol.packet :as pk]
[net.bowmap.protocol.packet.clientbound :as clientbound]
[net.bowmap.transport.readers :as readers]
[net.bowmap.protocol.packet.serverbound :as serverbound]
[net.bowmap.transport.writers :as writers]
[net.bowmap.transport.phase :as phase])
(:import
[io.netty.buffer Unpooled]))
; TODO docstrings
(defn build-clientbound-packet-id-index
[registry]
(into {}
(for [[phase packet-ids] registry
[i id] (map-indexed vector packet-ids)]
[{::phase/phase phase
::pk/id id}
i])))
(defn build-packet-writers
[registry]
(reduce (fn [acc [packet-id table]]
(assoc acc packet-id (writers/coerce table)))
{} registry))
(def clientbound-packet-ids (build-clientbound-packet-id-index clientbound/packet-order))
(def packet-encoders (build-packet-writers clientbound/packets))
(defn encode-packet!
"Encodes a packet into a frame.
Requires the connection phase, as packet ids are not unique across phases.
Several packets are logically the same across phases."
[packet phase]
(let [payload-writer (req! packet-encoders (::pk/id packet))]
(writers/length-prefixed (-> (Unpooled/buffer)
(writers/varint-> (req! clientbound-packet-ids {::pk/id (::pk/id packet) ::phase/phase phase}))
(payload-writer packet)))))
; Serverbound
(defn build-serverbound-packet-id-index [registry]
(into {}
(for [[phase packet-ids] registry
[i id] (map-indexed vector packet-ids)]
[{::phase/phase phase
::pk/numeric-id i}
id])))
(defn build-packet-readers [registry]
(reduce (fn [acc [packet-id table]]
(assoc acc packet-id
(let [reader (readers/coerce table)]
(fn [buf]
(assoc (reader buf)
::pk/id packet-id)))))
{} registry))
(def serverbound-packet-ids (build-serverbound-packet-id-index serverbound/packet-order))
(def packet-decoders (build-packet-readers serverbound/packets))
(defn decode-packet!
"Decodes a packet from a frame."
[frame phase]
(let [numeric-id (readers/->varint frame)
packet-id (req! serverbound-packet-ids {::phase/phase phase ::pk/numeric-id numeric-id})
decode-fn (req! packet-decoders packet-id)]
(decode-fn frame)))