f9703b2

Branches > main > f9703b2 > files / src / net / bowmap

Implement everything in the protocol up to registry data (oh boy)

Grahp, 2026-08-18

Commit: f9703b2dec6755752de923e7f29537fa12bd8a7f
Parent: 6cc1acd

6 changed files:

src/net/bowmap/network/client.clj modified (view file)

@@ -54,6 +54,7 @@     (OutputStream/.flush output-stream)))  (defn send-clientbound-packet [client packet]+  (println "sending packet out: " packet)   (write-frame!! (encode-packet! packet (req! client ::state/connection-state))                  (Socket/.getOutputStream (req! client ::socket)))   client)

src/net/bowmap/network/handle.clj modified (view file)

@@ -1,40 +1,150 @@ (ns net.bowmap.network.handle   (:require+   [net.bowmap.network.chunk :as chunk]    [net.bowmap.network.client :as client]    [net.bowmap.network.packet :as pk]    [net.bowmap.network.packets.clientbound :as clientbound]+   [net.bowmap.network.packets.registry :as registry]    [net.bowmap.network.packets.serverbound :as serverbound :refer [decode-packet!]]-   [net.bowmap.network.state :as state]))+   [net.bowmap.network.state :as state]+   [net.bowmap.server.gamemode :as gamemode]))  ; Handles incoming packets from clients +(defmulti handler+  (fn [client client-agent packet]+    (::pk/id packet)))++(defmethod handler :default [client a pk]+  (prn "Unhandled packet:" pk)+  client)++(defmethod handler ::serverbound/handshaking [client _ pk]+  (assoc client+         ::state/connection-state (req! pk :intent)+         :protocol-id (req! pk :protocol)))++(defmethod handler ::serverbound/status-request [client a _]+  (send a client/send-clientbound-packet+        {::pk/id ::clientbound/status-response+         ;; Should be un-bundled yeah.+         :response {:version {:name "26.2"+                              :protocol 776}+                    :players {:online 0+                              :max 1000}+                    ; Is this a text component? Could make that interface+                    :description {:text "Bowmap!"}+                    :enforcesSecureChat false}})+  client)++(defmethod handler ::serverbound/ping-request [client a pk]+  (send a client/send-clientbound-packet+        {::pk/id ::clientbound/pong-response+         :timestamp (:timestamp pk)})+  client)++(defmethod handler ::serverbound/login-start [client a pk]+  (let [{:keys! [uuid username]} pk]+    (send a client/send-clientbound-packet+          {::pk/id ::clientbound/login-success+           :profile {:uuid uuid+                     :username username+                     :properties []}+           :uuid uuid}))+  client)++(defmethod handler ::serverbound/login-acknowledged [client a pk]+  (send a client/send-clientbound-packet+        {::pk/id ::clientbound/known-packs+         ;; TODO also probably good to unbundle this+         :known-packs [{:namespace "minecraft"+                        :id "core"+                        :version "1.12.11"}]})+  (assoc client ::state/connection-state ::state/config))++(defmethod handler ::serverbound/known-packs [client a pk]+  (doseq [pk (registry/registry-packets)]+    (send a client/send-clientbound-packet pk))+  (send a client/send-clientbound-packet {::pk/id ::clientbound/finish-config})+  client)++(defn- build-chunk-messages []+  (let [pk {::pk/id ::clientbound/chunk-data-and-update-light+            :chunk-data+            (let [stone {:block-count (* 16 16 16)+                         :block-states {:bpe 0+                                        :palatte 1}+                         :biomes {:bpe 0+                                  :palatte 0}}+                  air {:block-count 0+                       :block-states {:bpe 0+                                      :palatte 0}+                       :biomes {:bpe 0+                                :palatte 0}}]+              {:data (cons stone (repeat (- chunk/world-height-chunk-sections 1) air))})+            :light-data {}}]+    (for [x (range -16 17)+          z (range -16 17)]+      (assoc pk+             :chunk-x x+             :chunk-z z))))++(defmethod handler ::serverbound/finish-config [client a pk]+  (send a client/send-clientbound-packet+        {::pk/id ::clientbound/login+         ;; TODO magic zero :p+         ;; I think you can keep a registry of entity ids and stick this on the client+         :entity-id 0+         :hardcore? false

Show all 173 lines

src/net/bowmap/network/packets/clientbound.clj modified (view file)

@@ -3,9 +3,9 @@    [net.bowmap.network.packet :as pk]    [net.bowmap.network.packets.writers :as write     :refer [bit-mask-> boolean-> byte-> chunk-data-> coerce context-optional->-            double-> enum-> float-> identifier-> int-> json-> length-prefixed-            light-data-> list-> long-> nbt-> optional-> or-> position->-            string-> ubyte-> uuid-> varint->]]+            double-> enum-> float-> game-profile-> identifier-> int-> json->+            length-prefixed light-data-> list-> long-> nbt-> optional-> or->+            position-> string-> ubyte-> uuid-> varint->]]    [net.bowmap.network.registry :as reg]    [net.bowmap.network.state :as state]    [net.bowmap.server.gamemode :as gamemode])@@ -189,11 +189,8 @@ (def packets   {::status-response [:response "Response to serverbound ::status-request" json->]    ::pong-response [:timestamp "The same timestamp as serverbound ::ping-request" long->]-   ::login-success [:uuid uuid->-                    :username string->-                    :properties (list-> [:name string->-                                         :value string->-                                         :signature (optional-> string->)])]+   ::login-success [:profile game-profile->+                    :uuid uuid->]    ::known-packs [:known-packs (list-> [:namespace string->                                         :id string->                                         :version string->])]

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

@@ -0,0 +1,14 @@+(ns net.bowmap.network.packets.registry+  (:require+   [net.bowmap.network.packet :as pk]+   [net.bowmap.network.packets.clientbound :as clientbound]+   [net.bowmap.network.registry :as reg]))++; Not in love with this...+(defn registry-packets []+  (for [[id m] (partition 2 reg/registries)]+    {::pk/id ::clientbound/registry-data+     ::reg/id id+     ::reg/entries (for [[entry-id data] m]+                     {::reg/entry-id entry-id+                      ::reg/entry-data data})}))

src/net/bowmap/network/packets/writers.clj modified (view file)

@@ -30,6 +30,7 @@       (CompositeByteBuf/.addComponent true buf)))  (defn string-> [buf s]+  {:pre [(string? s)]}   (doto buf     (varint-> (count s))     (ByteBuf/.writeCharSequence s (Charset/forName "UTF-8"))))@@ -67,6 +68,7 @@     (fn [buf m]       (write-table! buf table m)))) + (defn coerce   "If writer is an actual writer, returns it. If writer is a vector, turnes it into a table writer."   [writer]@@ -236,6 +238,12 @@       (boolean-> buf x)       (writer buf x)))) +(def game-profile-> (table-> [:uuid uuid->+                    :username string->+                    :properties (list-> [:name string->+                                         :value string->+                                         :signature (optional-> string->)])]))+ ; Chunks  ; TODO eventually encode pallates and the different values

src/net/bowmap/network/registry.clj modified (view file)

@@ -1,6 +1,7 @@ (ns net.bowmap.network.registry   (:require-   [net.bowmap.network.chunk :as chunk]))+   [net.bowmap.network.chunk :as chunk]+   [net.bowmap.network.packet :as pk]))  ;; Some way to keep track of order of these things and make that clear... ;; Probably a map of id -> order?@@ -81,6 +82,7 @@                                                        :whine_sound "minecraft:entity.wolf.ambient"}}]))  ;; Make a map of ids -> order+; This probably has to be per-client since different clients could have different registries #_(defn registry-id     "Function to get the ordered numerical id from a given registry id"     [id])