628768c

Branches > namespace-reorganization > 628768c > files / src / net / bowmap

Switch clientbound packets to use functions instead of macros

Grahp, 2026-02-27

Commit: 628768cbbe49e56824f5bba60570f7780d7c05da
Parent: 2bdfa58

7 changed files:

src/net/bowmap/core.clj modified (view file)

@@ -5,7 +5,7 @@    [net.bowmap.client.state :as state]    [net.bowmap.packet.read :as read]    [net.bowmap.packet-handling :as handle]-   [net.bowmap.packets.client :refer [encode-packet]]+   [net.bowmap.packet.client :refer [encode-packet]]    [net.bowmap.packet.server :as sp])   (:import    [io.netty.buffer ByteBuf Unpooled]

src/net/bowmap/packet/client.clj renamed from src/net/bowmap/packets/client.clj (view file)

@@ -1,47 +1,27 @@-(ns net.bowmap.packets.client+(ns net.bowmap.packet.client   "Clientbound packets"   (:require    [clojure.alpha.spec :as s]    [dev.grahp.error :refer [assert!]]    [net.bowmap.client.state :as state]-   [net.bowmap.codecs.write :as write :refer [write-varint!]]-   [net.bowmap.packet :as pk :refer [packet?]]-   [net.bowmap.packets.registry :as reg])+   [net.bowmap.packet :as pk]+   [net.bowmap.packet.write :as write])   (:import    [io.netty.buffer ByteBuf Unpooled])) -;; A lot of work to do in this file lol- ;; TODO this also looks identical to the serverbound packet ids...-(defmacro build-packet-ids [registry]+;; It is equally unreadable lmao+(defn build-packet-ids [registry]   (into {}         (mapcat (fn [[state packet-ids]]                   (into {} (map-indexed (fn [i pk] [{::state/state state ::pk/id pk} i]))                         packet-ids)))         registry)) -(defn build-packet [pk-name schema]-  (let [fn-name (symbol (str "encode-" (name pk-name) "-packet"))-        fields (map :field schema)-        types (map :type schema)-        codecs (map write/writer types)-        name-codec-pairs (for [codec codecs]-                           [(gensym) codec])-        codec-names (map first name-codec-pairs)-        bindings (apply concat name-codec-pairs)-        pairs? (map vector fields codec-names)-        buf (gensym "buf__")-        pk (gensym "pk__")]-    `(let [~@bindings]-       (fn ~fn-name [~buf ~pk]-         ~@(for [[field codec] pairs?]-             `(~codec ~buf (~field ~pk)))-         ~buf))))--(defmacro build-packets [registry]-  (reduce (fn [acc [packet-id schema]]-            (assoc acc packet-id (build-packet packet-id schema)))-          {} (reg/conform-registry registry)))+(defn build-packets [registry]+  (reduce (fn [acc [packet-id table]]+            (assoc acc packet-id (write/writer [:table table])))+          {} registry))  (def ^{:spec (s/map-of (s/schema [::state/state ::pk/id]) ::pk/numeric-id)}   packet-ids@@ -61,9 +41,6 @@      ::login-plugin-request      ::login-cookie-request]})) -(defn numeric-id [state id]-  (packet-ids {::state/state state ::pk/id id}))- (def ^{:spec (s/map-of ::pk/id (s/fspec :args (s/cat :buf #(instance? ByteBuf %) :pk ::pk/packet)                                         :ret #(instance? ByteBuf %)))}   packets@@ -76,19 +53,22 @@                                                  :value :string                                                  :signature [:optional :string]]]]]})) +(defn numeric-id [state id]+  (packet-ids {::state/state state ::pk/id id}))+ (defn packet-encoder [pk]   (packets (::pk/id pk)))  (defn encode-packet   "Encodes packet 'pk' into a ByteBuf of the packet bytes."   [pk state]-  {:pre [(packet? pk)]}+  {:pre [(pk/packet? pk)]}   (let [id (assert! (numeric-id state (::pk/id pk)))         encoder (assert! (packet-encoder pk))         data-buf (-> (Unpooled/buffer)-                     (write-varint! id)+                     (write/write-varint! id)                      (encoder pk))]     ;; This buffer only contains the data + a varint, which can never be larger than 5 bytes     (-> (Unpooled/buffer (+ (ByteBuf/.writerIndex data-buf) 5))-        (write-varint! (ByteBuf/.writerIndex data-buf))+        (write/write-varint! (ByteBuf/.writerIndex data-buf))         (ByteBuf/.writeBytes data-buf))))

src/net/bowmap/packet/read.clj modified (view file)

@@ -2,7 +2,7 @@   (:require    [clojure.alpha.spec :as s]    [dev.grahp.error :refer [ensure-not! raise]]-   [net.bowmap.packets.registry :as reg])+   [net.bowmap.packet.types :as t])   (:import    [io.netty.buffer ByteBuf]    [java.nio.charset Charset]@@ -76,7 +76,7 @@    :string read-string!    :uuid   read-uuid!    :table (fn [table]-            (let [table (->> (s/conform ::reg/table table)+            (let [table (->> (s/conform ::t/table table)                              ;; TODO make this :codec                              (mapv #(update % :type reader)))]               (fn [buf]

src/net/bowmap/packet/types.clj added (view file)

@@ -0,0 +1,8 @@+(ns net.bowmap.packet.types+  (:require+   [clojure.alpha.spec :as s]))++(s/def ::table+  (s/* (s/cat :field keyword?+              :doc (s/? string?)+              :type #(or (keyword? %) (vector? %)))))

src/net/bowmap/packet/write.clj renamed from src/net/bowmap/codecs/write.clj (view file)

@@ -1,14 +1,13 @@-(ns net.bowmap.codecs.write+(ns net.bowmap.packet.write   (:require-   [clojure.alpha.spec :as s]-   [clojure.data.json :as json]-   [dev.grahp.error :refer [raise]]-   [net.bowmap.codecs.types :as types]-   [net.bowmap.packets.registry :as reg])+    [clojure.alpha.spec :as s]+    [clojure.data.json :as json]+    [dev.grahp.error :refer [raise]]+    [net.bowmap.packet.types :as t])   (:import-   [io.netty.buffer ByteBuf Unpooled]-   [java.nio.charset Charset]-   [java.util UUID]))+    [io.netty.buffer ByteBuf]+    [java.nio.charset Charset]+    [java.util UUID]))  (defn write-varint! [buf n]   (loop [buf buf@@ -29,8 +28,10 @@   (write-string! buf (json/write-str s)))  (defn write-list! [buf t xs]+  ;; Reduce :p   (doseq [x xs]-    (t buf x)))+    (t buf x))+  buf)  (defn write-uuid! [buf uuid]   (ByteBuf/.writeLong buf (UUID/.getMostSignificantBits uuid))@@ -39,14 +40,15 @@ ;; TODO this is where optionality and nil checking should be, and the packet stuff should use this. (defn write-table! [buf t? m]   (doseq [{:keys [field type]} t?]-    (type buf (get m field))))+    (type buf (get m field)))+  buf)  (declare writers)  ;; I think this should have :required/:optional/:prefixed-optional, ;; and have it that non-optional fields are implicity :required and thus nil checked (defn writer-  "Returns a form that will evaluate to a function that takes a buffer and writes the respective type to it."+  ""   [t]   (if (vector? t)     (let [[t & args] t]@@ -64,29 +66,35 @@     (codec buf x)     buf)) +(defn write-optional! [buf codec x]+  (write-boolean! buf x)+  (write-context-optional! buf codec x))+ (def writers-  {:byte   `ByteBuf/.writeByte-   :ubyte  `ByteBuf/.writeByte-   :short  `ByteBuf/.writeShort-   :ushort `ByteBuf/.writeShort-   :int    `ByteBuf/.writeInt-   :long   `ByteBuf/.writeLong-   :varint `write-varint!-   :string `write-string!-   :json   `write-json!-   :uuid   `write-uuid!+  {:byte   ByteBuf/.writeByte+   :ubyte  ByteBuf/.writeByte+   :short  ByteBuf/.writeShort+   :ushort ByteBuf/.writeShort+   :int    ByteBuf/.writeInt+   :long   ByteBuf/.writeLong+   :varint write-varint!+   :string write-string!+   :json   write-json!+   :uuid   write-uuid!+    ;; TODO These are kinda named backwards...    :context-optional (fn [t]-                       `(fn ~'write-context-optional [buf# x#]-                          (write-context-optional! buf# ~(writer t) x#)))+                       (let [codec (writer t)]+                         (fn [buf x]+                           (write-context-optional! buf codec x))))    :optional (fn [t]-               `(fn ~'write-optional [buf# x#]-                  (write-boolean! buf# x#)-                  (write-context-optional! buf# ~(writer t) x#)))+               (let [codec (writer t)]+                 (fn [buf x]+                   (write-optional! buf codec x))))    :table  (fn [t]-             ;; TODO needs to be moved yeah.-             (let [t (->> (s/conform ::reg/table t)-                          (mapv #(update % :type writer)))]-               `(fn ~'write-table [buf# m#] (write-table! buf# ~t m#))))+             (let [t? (->> (s/conform ::t/table t)+                           (mapv #(update % :type writer)))]+               (fn [buf m] (write-table! buf t? m))))    :list   (fn [t]-             `(fn ~'write-list [buf# xs#] (write-list! buf# ~(writer t) xs#)))})+             (let [codec (writer t)]+               (fn [buf xs] (write-list! buf codec xs))))})

src/net/bowmap/packet_handling.clj modified (view file)

@@ -2,7 +2,7 @@   (:require    [net.bowmap.client.state :as state]    [net.bowmap.packet :as pk]-   [net.bowmap.packets.client :as cp]+   [net.bowmap.packet.client :as cp]    [net.bowmap.packet.server :as sp]))  (defmulti handle-packet

src/net/bowmap/packets/registry.clj deleted (view file)

@@ -1,21 +0,0 @@-(ns net.bowmap.packets.registry-  (:require-   [clojure.alpha.spec :as s]-   [dev.grahp.error :refer [raise]]-   [net.bowmap.packet :as pk]))--(s/def ::table-  (s/* (s/cat :field keyword?-              :doc (s/? string?)-              :type #(or (keyword? %) (vector? %)))))--(s/def ::packet-registry-  (s/map-of ::pk/id ::table))--(defn conform-registry-  "Returns a registry conformed to '::packet-registry', or throws if it is invalid"-  [registry]-  (let [registry (s/conform ::packet-registry registry)]-    (if (= ::s/invalid registry)-      (raise "Invalid packet registry!" {:explanation (s/explain-data ::packet-registry registry)})-      registry)))