4f918a3
Branches > main > 4f918a3 > files / src / net / bowmap
Add packet schemas needed for server list ping
Commit: 4f918a347d9c1535b31a3adf44ccc7b3aa8a20b7
Parent: f2af1d9
5 changed files:
deps.edn view file
@@ -3,4 +3,5 @@ :extra-deps {nrepl/nrepl {:mvn/version "1.7.0"}}}} :deps {org.clojure/clojure {:mvn/version "1.13.0-alpha6"}+ org.clojure/data.json {:mvn/version "2.5.2"} io.netty/netty-buffer {:mvn/version "4.1.111.Final"}}}src/net/bowmap/network/clientbound_packets.clj view file
@@ -1,5 +1,7 @@ (ns net.bowmap.network.clientbound-packets (:require+ [net.bowmap.network.frame.types :as t]+ [net.bowmap.network.frame.writers :refer :all] [net.bowmap.network.phase :as phase])) (defn ? [_] (throw (Exception. "Error while encoding packet: no packet definition for that packet id")))@@ -7,8 +9,8 @@ (def clientbound-packets "Map of connection phases to pairs of [clientbound-packet-id writer]" {::phase/status- [::status-response ?- ::pong-response ?]+ [::status-response [::t/status-response json->]+ ::pong-response [::t/timestamp long->]] ::phase/login [::disconnect ? ::encryption-request ?src/net/bowmap/network/frame/readers.clj view file
@@ -0,0 +1,39 @@+(ns net.bowmap.network.frame.readers+ "Functions for reading values from frames.+ Functions look like ->type, where 'type' is a Minecraft protocol type.+ See https://minecraft.wiki/w/Java_Edition_protocol/Packets#Data_types"+ (:require+ [net.bowmap.network.frame.types :refer [max-varint-size]])+ (:import+ [io.netty.buffer ByteBuf]+ [java.nio.charset Charset]))++(def ->byte ByteBuf/.readByte)+(def ->ubyte (comp unchecked-byte ByteBuf/.readByte))+(def ->short ByteBuf/.readShort)+(def ->ushort (comp unchecked-short ByteBuf/.readShort))+(def ->int ByteBuf/.readInt)+(def ->long ByteBuf/.readLong)+(def ->float ByteBuf/.readFloat)+(def ->double ByteBuf/.readDouble)++(defn ->varint [buf]+ (loop [num-read 0+ result 0]+ (if (>= num-read max-varint-size)+ (throw (Exception. "VarInt too long"))+ (let [b (ByteBuf/.readByte buf)+ result' (bit-or result (bit-shift-left (bit-and b 0x7F) (* 7 num-read)))]+ (if (zero? (bit-and b 0x80))+ result'+ (recur (inc num-read) result'))))))++(defn ->string [buf]+ (let [len (->varint buf)]+ (if (neg? len)+ (throw (Exception. "String length cannot be negative"))+ (ByteBuf/.readCharSequence buf len (Charset/forName "UTF-8")))))++(defn ->enum [reader m]+ (fn [buf]+ (m (reader buf))))src/net/bowmap/network/frame/writers.clj view file
@@ -0,0 +1,37 @@+(ns net.bowmap.network.frame.writers+ "Functions for writing values into frames.+ Functions look like type->, where 'type' is a Minecraft protocol type.+ See https://minecraft.wiki/w/Java_Edition_protocol/Packets#Data_types"+ (:require+ [clojure.data.json :as json])+ (:import+ [io.netty.buffer ByteBuf]+ [java.nio.charset Charset]))++(def byte-> ByteBuf/.writeByte)+(def ubyte-> ByteBuf/.writeByte)+(def short-> ByteBuf/.writeShort)+(def ushort-> ByteBuf/.writeShort)+(def int-> ByteBuf/.writeInt)+(def long-> ByteBuf/.writeLong)+(def float-> ByteBuf/.writeFloat)+(def double-> ByteBuf/.writeDouble)++(defn varint-> [buf n]+ (loop [buf buf+ n n]+ (let [b (bit-and n 0x7F)+ nxt (unsigned-bit-shift-right n 7)]+ (if (zero? nxt)+ (ByteBuf/.writeByte buf b)+ (recur (ByteBuf/.writeByte buf (bit-or b 0x80))+ nxt)))))++(defn string-> [buf s]+ {:pre [(string? s)]}+ (doto buf+ (varint-> (count s))+ (ByteBuf/.writeCharSequence s (Charset/forName "UTF-8"))))++(defn json-> [buf s]+ (string-> buf (json/write-str s)))src/net/bowmap/network/serverbound_packets.clj view file
@@ -1,14 +1,19 @@ (ns net.bowmap.network.serverbound-packets (:require+ [net.bowmap.network.frame.readers :refer :all]+ [net.bowmap.network.frame.types :as t] [net.bowmap.network.phase :as phase])) (def serverbound-packets "Map of connection phases to pairs of [serverbound-packet-id reader]" {::phase/handshaking- [::handshaking []]+ [::handshaking [:protocol ->varint+ :address ->string+ :port ->short+ ::phase/phase (->enum ->varint {1 ::phase/status 2 ::phase/login 3 ::phase/transfer})]] ::phase/status [::status-request []- ::ping-request []]+ ::ping-request [::t/timestamp ->long]] ::phase/login [::login-start [] ::encryption-response []