packets.clj
Branches > main > e860102 > files / src / net / bowmap / server / protocol / packets.clj
(ns net.bowmap.server.protocol.packets
(:require
[net.bowmap.server.protocol.clientbound-packets :refer [clientbound-packets]]
[net.bowmap.server.protocol.readers :as readers]
[net.bowmap.server.protocol.types :refer [frame]]
[net.bowmap.server.protocol.writers :as writers]
[net.bowmap.server.protocol.packet :as packet]
[net.bowmap.server.protocol.phase :as phase]
[net.bowmap.server.protocol.serverbound-packets :refer [serverbound-packets]]))
(defn- find-indexed
"Takes a seq of pairs and returns both the index of the first pair
'keyed' by the given id and its 'value' in linear time.
E.g. (find-indexed [:a [] :b {} :c #{}] :b) -> [1 {}]"
[id pairs]
(some (fn [[i [k v]]]
(when (= id k)
[i v]))
(map-indexed vector (partition 2 pairs))))
(defn encode-packet
"Encodes a packet into a frame.
Throws when the packet cannot be encoded."
[{::phase/keys! [phase]} {::packet/keys! [id] :as packet}]
(let [schemas (clientbound-packets phase)
[numeric-id schema] (find-indexed id schemas)
payload-writer (writers/to-writer schema)]
(writers/length-prefixed
(-> (frame)
(writers/varint-> numeric-id)
(payload-writer packet)))))
(defn decode-frame
"Decodes a packet from a frame.
Can throw if the frame does not contain a valid packet."
[{:keys! [::phase/phase]} frame]
(let [numeric-id (readers/->varint frame)
schemas (serverbound-packets phase)
[id schema] (nth (partition 2 schemas) numeric-id)
payload-reader (readers/to-reader schema)]
(assoc (payload-reader frame)
::packet/id id)))