2bdfa58
Branches > client-handling-rewrite > 2bdfa58 > files / src / net / bowmap
Switch serverbound packets to use functions instead of macros
Commit: 2bdfa5851366ac376959c7aedd61235cb5cc1740
Parent: 92885b7
4 changed files:
src/net/bowmap/core.clj view file
@@ -3,10 +3,10 @@ [aleph.tcp :as tcp] [manifold.stream :as s] [net.bowmap.client.state :as state]- [net.bowmap.codecs.read :as read]+ [net.bowmap.packet.read :as read] [net.bowmap.packet-handling :as handle] [net.bowmap.packets.client :refer [encode-packet]]- [net.bowmap.packets.server :as sp])+ [net.bowmap.packet.server :as sp]) (:import [io.netty.buffer ByteBuf Unpooled] [io.netty.channel ChannelOption]))src/net/bowmap/packet/read.clj src/net/bowmap/codecs/read.clj view file
@@ -1,6 +1,8 @@-(ns net.bowmap.codecs.read+(ns net.bowmap.packet.read (:require- [dev.grahp.error :refer [ensure-not! raise]])+ [clojure.alpha.spec :as s]+ [dev.grahp.error :refer [ensure-not! raise]]+ [net.bowmap.packets.registry :as reg]) (:import [io.netty.buffer ByteBuf] [java.nio.charset Charset]@@ -44,26 +46,40 @@ (defn read-enum! [codec m buf] (m (codec buf))) -(defn read-array [codec len buf])+#_(defn read-array [codec len buf]) -(declare readers reader)+(defn read-table! [buf table]+ (reduce (fn [acc {:keys [field type]}]+ (assoc acc field (type buf)))+ {} table))++(declare readers) (defn reader- "Returns a form that will evaluate to a function that takes a buffer and reads the respective type from it."- ([t]- (or (readers t) (raise "No such type!" {:type t})))- ([t & args]- (apply (reader t) args)))+ "Returns a function of a ByteBuf that reads the respective type.+ Will throw if no such type exists."+ [t]+ (if (vector? t)+ (let [[t & args] t]+ (apply (reader t) args))+ (or (readers t)+ (raise (str "No such type! " (name t)) {:type t})))) (def readers- {:byte `ByteBuf/.readByte- :ubyte `(comp unchecked-byte ByteBuf/.readByte)- :short `ByteBuf/.readShort- :ushort `(comp unchecked-short ByteBuf/.readShort)- :int `ByteBuf/.readInt- :long `ByteBuf/.readLong- :varint `read-varint!- :string `read-string!- :uuid `read-uuid!+ {:byte ByteBuf/.readByte+ :ubyte (comp unchecked-byte ByteBuf/.readByte)+ :short ByteBuf/.readShort+ :ushort (comp unchecked-short ByteBuf/.readShort)+ :int ByteBuf/.readInt+ :long ByteBuf/.readLong+ :varint read-varint!+ :string read-string!+ :uuid read-uuid!+ :table (fn [table]+ (let [table (->> (s/conform ::reg/table table)+ ;; TODO make this :codec+ (mapv #(update % :type reader)))]+ (fn [buf]+ (read-table! buf table)))) :enum (fn [t m]- `(fn [buf#] (read-enum! ~(reader t) ~m buf#)))})+ (fn [buf] (read-enum! (reader t) m buf)))})src/net/bowmap/packet/server.clj src/net/bowmap/packets/server.clj view file
@@ -1,59 +1,25 @@-(ns net.bowmap.packets.server+(ns net.bowmap.packet.server (:require [clojure.alpha.spec :as s] [dev.grahp.error :refer [raise]] [net.bowmap.client.state :as state]- [net.bowmap.codecs.read :as read]- [net.bowmap.packet :as pk]- [net.bowmap.packets.registry :as reg])+ [net.bowmap.packet.read :as read]+ [net.bowmap.packet :as pk]) (:import [io.netty.buffer ByteBuf])) -;; Surely there's a better way to do that lmao-;; TODO turned into 'reader'-(defn type->codec- "Takes a type from net.bowmap.codecs.read and returns a form that will evaluate to a function to decode that type from a ByteBuffer"- [t]- (if (vector? t)- (apply read/reader t)- (read/reader t)))+(defn build-packets [registry]+ (reduce (fn [acc [packet-id table]]+ (assoc acc packet-id+ (let [reader (read/reader [:table table])]+ (fn [buf]+ (assoc (reader buf)+ ::pk/id packet-id)))))+ {} registry)) -(defn build-packet [packet-id schema]- (let [fn-name (symbol (str "decode-" (name packet-id) "-packet"))- buf (gensym "buf__")-- fields (map :field schema)- types (map :type schema)- name-codec-pairs (for [t types]- [(gensym "decode__") (type->codec t)])- codec-calls (for [[codec-binding] name-codec-pairs]- `(~codec-binding ~buf))- names->codecs (apply concat name-codec-pairs)]- `(let [~@names->codecs]- (fn ~fn-name [~buf]- (hash-map ::pk/id ~packet-id- ~@(interleave fields codec-calls))))))--(defmacro build-packets [registry]- (reduce (fn [acc [packet-id schema]]- (assoc acc packet-id (build-packet packet-id schema)))- {} (reg/conform-registry registry)))--(def ^{:spec (s/map-of ::pk/id (s/fspec :args (s/cat :buf #(instance? ByteBuf %))- :ret ::pk/packet))}- packets- (build-packets- {::handshaking [:protocol :varint- :address :string- :port :short- :intent [:enum :varint {1 ::state/status 2 ::state/login 3 ::state/transfer}]]- ::status-request []- ::ping-request [:timestamp :long]- ::login-start [:username :string- :uuid :uuid]})) ;; TODO this is unreadable lol-(defmacro build-packet-ids [registry]+(defn build-packet-ids [registry] (into {} (mapcat (fn [[state packet-ids]] (into {}@@ -76,6 +42,19 @@ ::login-acknowledged ::login-cookie-response]})) +(def ^{:spec (s/map-of ::pk/id (s/fspec :args (s/cat :buf #(instance? ByteBuf %))+ :ret ::pk/packet))}+ packets+ (build-packets+ {::handshaking [:protocol :varint+ :address :string+ :port :short+ :intent [:enum :varint {1 ::state/status 2 ::state/login 3 ::state/transfer}]]+ ::status-request []+ ::ping-request [:timestamp :long]+ ::login-start [:username :string+ :uuid :uuid]}))+ (defn decode-packet! "Decodes and returns one packet from ByteBuf 'buf', which should contain at least one readable packet. The initial length field of the packet should not be stripped from 'buf'.src/net/bowmap/packet_handling.clj view file
@@ -3,7 +3,7 @@ [net.bowmap.client.state :as state] [net.bowmap.packet :as pk] [net.bowmap.packets.client :as cp]- [net.bowmap.packets.server :as sp]))+ [net.bowmap.packet.server :as sp])) (defmulti handle-packet (fn [pk client]