frame.clj

Bowmap · bowmap.git · Tickets

Branches > main > e9e2047 > files / src / net / bowmap / server / protocol / frame.clj

(ns net.bowmap.server.protocol.frame
  (:require
   [clojure.spec.alpha :as s])
  (:import
   [io.netty.buffer ByteBuf Unpooled]))

(defprotocol Frame
  "A immutable sequence of bytes representing one framed, serialized Minecraft protocol packet.
   Frames contain the packet's numeric id and payload, but are not length-prefixed.
   See https://minecraft.wiki/w/Java_Edition_protocol/Packets for the packet format."
  (write! [frame f] "Calls 'f' with the array and length of the frame."))

(s/def ::frame #(satisfies? Frame %))

(defn frame
  ([array] (frame array (alength array)))
  ([array length]
   ^{:type ::frame}
   (reify Frame
     (write! [_ f] (f array length)))))

(defmethod print-method ::frame [frame writer]
  (write! frame
          (fn [array length]
            (.write writer "#Frame ")
            (.write writer (pr-str (subvec (vec array) 0 length))))))

(defn ->ByteBuf
  "Returns a read-only ByteBuf containing the bytes of a frame."
  [frame]
  (write! frame
          (fn [array length]
            (ByteBuf/.asReadOnly (Unpooled/wrappedBuffer array 0 length)))))