083e2e7

Branches > facts > 083e2e7 > files / src / net / bowmap

Use a ref for client state

Grahp, 2026-08-20

Commit: 083e2e72d5aec9c4f2e40f4387f9365685e914d4
Parent: 108a097

3 changed files:

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

@@ -1,32 +1,23 @@ (ns net.bowmap.network.client   (:require    [net.bowmap.network.packets.clientbound :refer [encode-packet!]]+   [net.bowmap.network.packets.serverbound :refer [decode-packet!]]    [net.bowmap.network.state :as state]-   [net.bowmap.network.streams :as streams]-   [net.bowmap.server.entity :as entity]-   [net.bowmap.server.server :as server])+   [net.bowmap.network.streams :as streams])   (:import    [java.net Socket])) -(defn send-clientbound-packet [client packet]-  #_(println "sending packet out: " packet)-  (streams/write-frame!! (encode-packet! packet (req! client ::state/connection-state))-                         (Socket/.getOutputStream (req! client ::socket)))-  client)--(defn leave! [client-agent]-  (try-    (dosync-      (when-let [uuid (::entity/uuid @client-agent)]-        (commute server/players dissoc uuid)))-    (finally-      (Socket/.close (req! @client-agent ::socket)))))- (defn client [socket]-  (agent {::socket socket-          ::state/connection-state ::state/handshaking}-         :error-handler (fn [a ex]-                          (try-                            (Throwable/.printStackTrace ex *err*)-                            (finally-                              (leave! a))))))+  (ref {::state/connection-state ::state/handshaking+        ::socket socket}))++(defn read-packet! [client-ref]+  (let [{:keys! [::socket ::state/connection-state]} @client-ref+        frame (streams/read-frame!! (Socket/.getInputStream socket))]+    (decode-packet! frame connection-state)))++(defn send-packet! [client-ref packet]+  (let [{:keys! [::socket ::state/connection-state]} @client-ref]+    #_(println "sending packet out: " packet)+    (streams/write-frame!! (encode-packet! packet connection-state) (Socket/.getOutputStream socket))+    client))

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

@@ -1,187 +1,42 @@ (ns net.bowmap.network.handle   (:require-   [net.bowmap.network.chunk :as chunk]-   [net.bowmap.network.client :as client]+   [net.bowmap.network.client :refer [send-packet!]]    [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.registry :as reg]+   [net.bowmap.network.packets.serverbound :as serverbound]    [net.bowmap.network.state :as state]-   [net.bowmap.server.entity :as entity]-   [net.bowmap.server.gamemode :as gamemode]    [net.bowmap.server.server :as server])) -; Handles incoming packets from clients--(defmulti handler+(defmulti handle-packet   (fn [client packet]     (::pk/id packet))) -(defmethod handler :default [client pk]-  #_(prn "Unhandled packet:" pk)-  client)+(defmethod handle-packet :default [client _]+  {:client client}) -(defmethod handler ::serverbound/handshaking [client pk]-  (assoc client-         ::state/connection-state (req! pk :intent)-         :protocol-id (req! pk :protocol)))+(defmethod handle-packet ::serverbound/handshaking [client pk]+  (let [{:keys! [intent protocol]} pk]+    {:client (assoc client+                    ::state/connection-state intent+                    :protocol-id protocol)}))  ; TODO move to a fact and the game logic handler :)-(defmethod handler ::serverbound/status-request [client _]-  (client/send-clientbound-packet client-        {::pk/id ::clientbound/status-response-         ;; Should be un-bundled yeah.-         :response {:version {:name "26.2"-                              :protocol 776}-                    :players {:online (count @server/players)-                              :max server/max-player-count}-                    ; Is this a text component? Could make that interface-                    :description {:text "Bowmap!"}-                    :enforcesSecureChat false}}))+(defmethod handle-packet ::serverbound/status-request [client _]+  {:client client+   :packets [{::pk/id ::clientbound/status-response+              ;; Should be un-bundled yeah.+              :response {:version {:name "26.2"+                                   :protocol 776}+                         :players {:online (count @server/players)+                                   :max server/max-player-count}+                         ; Is this a text component? Could make that interface+                         :description {:text "Bowmap!"}+                         :enforcesSecureChat false}}]}) -(defmethod handler ::serverbound/ping-request [client pk]-  (client/send-clientbound-packet-    client-    {::pk/id ::clientbound/pong-response-     :timestamp (:timestamp pk)}))--(defmethod handler ::serverbound/login-start [client pk]-  (let [{:keys! [uuid username]} pk]-    (client/send-clientbound-packet-      (assoc client ::entity/uuid uuid)-      {::pk/id ::clientbound/login-success-       :profile {:uuid uuid-                 :username username-                 :properties []}-       :session-id (random-uuid)})))--(defmethod handler ::serverbound/login-acknowledged [client _]-  (client/send-clientbound-packet-    (assoc client ::state/connection-state ::state/config)-    {::pk/id ::clientbound/known-packs-     ;; TODO also probably good to unbundle this-     :known-packs [{:namespace "minecraft"-                    :id "core"-                    :version "26.2"}]}))--(defmethod handler ::serverbound/known-packs [client _]-  (doseq [pk (registry/registry-packets)]-    (client/send-clientbound-packet client pk))--  ; TODO ofc move these to the registry :p-  (client/send-clientbound-packet client {::pk/id ::clientbound/update-tags-                                          :tagged-registries [{:registry "minecraft:block"-                                                               :tags [{:tag-name "bowmap:infiniburn"-                                                                       :entries []}]}]})-  (client/send-clientbound-packet client {::pk/id ::clientbound/update-tags-                                          :tagged-registries [{:registry "minecraft:damage_type"

Show all 215 lines

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

@@ -1,9 +1,8 @@ (ns net.bowmap.network.server   (:require    [clojure.core.async :refer [io-thread]]-   [net.bowmap.network.client :as client :refer [leave!]]-   [net.bowmap.network.handle :as handle]-   [net.bowmap.network.streams :as streams])+   [net.bowmap.network.client :as client]+   [net.bowmap.network.handle :as handle])   (:import    [java.io EOFException]    [java.net ServerSocket Socket SocketException]))@@ -12,17 +11,15 @@   (let [server (ServerSocket. port)]     (loop []       (let [socket (ServerSocket/.accept server)-            input-stream (Socket/.getInputStream socket)-            client-agent (client/client socket)]+            client-ref (client/client socket)]         (io-thread           (try             (loop []               ; TODO this is another way the client can leave!-              (let [frame (streams/read-frame!! input-stream)]-                (send client-agent handle/process-serverbound-frame frame))+              (handle/handle!! client-ref (client/read-packet! client-ref))               (recur))             (catch EOFException _)             (catch SocketException _)             (finally-              (leave! client-agent)))))+              (Socket/.close socket)))))       (recur))))