5e3f500

Branches > main > 5e3f500 > files / src / net / bowmap

Add facts and responses!!!

Grahp, 2026-08-20

Commit: 5e3f500ca8d7cc7c82faed856e5352706a8a7463
Parent: 50671f1

5 changed files:

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

@@ -11,35 +11,29 @@    [net.bowmap.network.state :as state]    [net.bowmap.server.entity :as entity]    [net.bowmap.server.gamemode :as gamemode]-   [net.bowmap.server.server :as server]))+   [net.bowmap.server.logic :as logic]+   [net.bowmap.server.server :as server]+   [net.bowmap.stormbow.fact :as fact]+   [net.bowmap.stormbow.responses :refer [handle-responses!]]))  (defmulti handle-packet   (fn [client packet]     (::pk/id packet)))  (defmethod handle-packet :default [client _]-  {:client client-   :packets []})+  {:client client})  (defmethod handle-packet ::serverbound/handshaking [client pk]   (let [{:keys! [intent protocol]} pk]     {:client (assoc client                     ::state/connection-state intent-                    :protocol-id protocol)-     :packets []}))+                    :protocol-id protocol)}))  ; TODO move to a fact and the game logic handler :) (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}}]})+   :facts [{::fact/id ::fact/server-list-requested+            ::client/client client}]})  (defmethod handle-packet ::serverbound/ping-request [client pk]   {:client client@@ -176,8 +170,13 @@  (defn handle!! [client-ref packet]   (dosync-    (let [{:keys! [client packets] :keys [keepalive?]} (handle-packet @client-ref packet)]+    ; May want sync-facts vs. async-facts?+    ; The facts themselves shouldn't care but the handler might+    (let [{:keys! [client] :keys [packets facts keepalive?]} (handle-packet @client-ref packet)]       (ref-set client-ref client)       (let [{:keys! [::connection/connection ::state/connection-state]} @client-ref]         (doseq [pk packets]-          (send connection connection/send-frame-action! (clientbound/encode-packet! pk connection-state)))))))+          (send connection connection/send-frame-action! (clientbound/encode-packet! pk connection-state)))+        ; TODO re-re-add keepalive+        (doseq [fact facts]+          (handle-responses! (logic/handle-fact fact)))))))

src/net/bowmap/server/logic.clj added (view file)

@@ -0,0 +1,28 @@+(ns net.bowmap.server.logic+  (:require+    [net.bowmap.network.client :as client]+    [net.bowmap.server.server :as server]+    [net.bowmap.stormbow.fact :as fact]+    [net.bowmap.stormbow.response :as response]))++(defmulti handler+  (fn [fact]+    (::fact/id fact)))++; TODO see the comment on responses.clj+; But this is also being called within a transaction and assuming that so I'm not sure+(defmethod handler ::fact/server-list-requested [fact]+  (let [{:keys! [::client/client]} fact]+    [{::response/id ::response/send-server-list+      ::client/client client+      :server-list-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}}]))++; Returns a seq of responses+(defn handle-fact [fact]+  (handler fact))

src/net/bowmap/stormbow/fact.clj added (view file)

@@ -0,0 +1,6 @@+(ns net.bowmap.stormbow.fact+  (:require+   [clojure.spec.alpha :as s]))++(s/def ::fact (s/keys :opt [::id]))+(s/def ::id qualified-keyword?) ; Could use a set of all facts

src/net/bowmap/stormbow/response.clj added (view file)

@@ -0,0 +1,6 @@+(ns net.bowmap.stormbow.response+  (:require+   [clojure.spec.alpha :as s]))++(s/def ::response (s/keys :opt [::id]))+(s/def ::id qualified-keyword?)

src/net/bowmap/stormbow/responses.clj added (view file)

@@ -0,0 +1,28 @@+(ns net.bowmap.stormbow.responses+  (:require+   [net.bowmap.network.client :as client]+   [net.bowmap.network.connection :as connection]+   [net.bowmap.network.packet :as pk]+   [net.bowmap.network.packets.clientbound :as clientbound :refer [encode-packet!]]+   [net.bowmap.network.state :as state]+   [net.bowmap.stormbow.response :as response]))++(defmulti handle-response!+  (fn [response]+    (::response/id response)))++::client/client ::state/connection-state++; TODO currently this must always happen within a transaction, but that's no good!+; This is being called _always_ synchronously from the packet handler, which is also no good for even more reasons+; So, figure out how to not do that?+(defmethod handle-response! ::response/send-server-list [response]+  (let [{:keys! [::client/client server-list-response]} response+        {:keys! [::state/connection-state ::connection/connection]} client+        packet {::pk/id ::clientbound/status-response+                :response server-list-response}+        frame (encode-packet! packet connection-state)]+    (send connection connection/send-frame-action! frame)))++(defn handle-responses! [responses]+  (run! handle-response! responses))