a35eba5

Branches > main > a35eba5 > files / .gitignore

Remove core.async from connections

Grahp, 2026-08-25

Commit: a35eba5a4cfdae3c37f2ae028d97d81ba8aee7be
Parent: 8ee8c07

3 changed files:

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

@@ -1,6 +1,5 @@ (ns net.bowmap.protocol.server   (:require-   [clojure.core.async :refer [<!! io-thread put!]]    [net.bowmap.protocol.handle :as handle]    [net.bowmap.server.logic :as logic]    [net.bowmap.server.player :as player]@@ -9,23 +8,21 @@    [net.bowmap.transport.connection :as connection]    [net.bowmap.transport.server :as mc])) -(defn handle-response [clientbound-packets {:keys [packets events]}]+(defn handle-response [send-packet {:keys [packets events]}]   (doseq [packet packets]-    (put! clientbound-packets packet))+    (send-packet packet))   (doseq [event events]     (execute-effects! (logic/handle-events event))))  (defn handle-connection [connection]-  (let [{::connection/keys! [close-fn serverbound-packets clientbound-packets closed]} connection]-    (io-thread-      (when-let [uuid @closed]-        (execute-effects! (logic/handle-events {::event/id ::event/player-left ::player/uuid uuid}))))+  (let [{::connection/keys! [close-fn send-packet receive-packet]} connection]     (try       (loop []-        (handle-response clientbound-packets (handle/interpret-packet (<!! serverbound-packets)))+        (handle-response send-packet (handle/interpret-packet (assoc (receive-packet) ::connection/connection connection)))         (recur))       (finally-        (close-fn)))))+        (when-let [uuid (close-fn)]+          (execute-effects! (logic/handle-events {::event/id ::event/player-left ::player/uuid uuid})))))))  (defn start-server! [port]   (mc/start-server! port #'handle-connection))

src/net/bowmap/stormbow/effect_execution.clj modified (view file)

@@ -1,6 +1,5 @@ (ns net.bowmap.stormbow.effect-execution   (:require-   [clojure.core.async :refer [put!]]    [net.bowmap.protocol.packet :as pk]    [net.bowmap.protocol.packet.clientbound :as clientbound]    [net.bowmap.server.player :as player]@@ -14,9 +13,9 @@  (defmethod execute-effect! ::effect/send-chat-message [{::player/keys! [uuid] :keys! [message]}]   (let [{::connection/keys! [connection]} (@server/players uuid)-        {::connection/keys! [clientbound-packets]} connection]-    (put! clientbound-packets {::pk/id ::clientbound/system-chat-message-                               :message message})))+        {::connection/keys! [send-packet]} connection]+    (send-packet {::pk/id ::clientbound/system-chat-message+                  :message message})))  (defn execute-effects! [effects]   (run! execute-effect! effects))

src/net/bowmap/transport/connection.clj modified (view file)

@@ -1,84 +1,69 @@ (ns net.bowmap.transport.connection   "A connection to the Minecraft server."   (:require-   [clojure.core.async :refer [<!! chan close! io-thread put! timeout]]+   [clojure.core.async :refer [io-thread]]    [net.bowmap.protocol.packet :as pk]    [net.bowmap.protocol.packet.clientbound :as clientbound]    [net.bowmap.protocol.packet.serverbound :as serverbound]-   [net.bowmap.transport.phase :as phase]    [net.bowmap.server.player :as player]    [net.bowmap.transport.packets :refer [decode-packet! encode-packet!]]+   [net.bowmap.transport.phase :as phase]    [net.bowmap.transport.streams :as streams])   (:import    [java.io EOFException]    [java.net Socket SocketException])) -(defn handle-serverbound-frame!-  [state conn frame]-  (let [{::phase/keys! [phase]} @state-        packet (decode-packet! frame phase)]-    (when-let [{::pk/keys! [id]} packet]-      (case id-        ::serverbound/handshaking        (swap! state assoc ::phase/phase (req! packet ::phase/phase))-        ::serverbound/login-acknowledged (swap! state assoc ::phase/phase ::phase/config)-        ::serverbound/finish-config      (swap! state assoc ::phase/phase ::phase/play)-        ::serverbound/login-start-        (let [{:keys! [username uuid]} packet]-          (swap! state assoc ::player/username username ::player/uuid uuid))-        nil)-      ; Just kinda crudely passing the connection into the serverbound packet right now-      (merge packet {::connection conn} (select-keys @state [::player/uuid])))))- (defn connection   "Creates a connection object from a java.net.Socket    Connections have a channel of serverbound packets, and a channel of clientbound packets.    Connections can be closed with ::close-fn, and the promise at ::closed will deliver with    the connection's known uuid, or nil if the connection does not have one."   [socket]-  (let [serverbound-packets (chan 64)-        clientbound-packets (chan 64)-        input-stream (Socket/.getInputStream socket)+  (let [input-stream (Socket/.getInputStream socket)         output-stream (Socket/.getOutputStream socket)         state (atom {::phase/phase ::phase/handshaking})         closed-promise (promise)-        conn {::close-fn (fn []-                           (Socket/.close socket)-                           (close! serverbound-packets)-                           (close! clientbound-packets))-              ::closed closed-promise-              ::serverbound-packets serverbound-packets-              ::clientbound-packets clientbound-packets}]-+        close (fn []+                (Socket/.close socket)+                (deliver closed-promise (@state ::player/uuid))+                (@state ::player/uuid))+        conn {::close-fn close+              ::send-packet (fn [packet]+                              (when (Socket/.isClosed socket)+                                (throw (ex-info "Tried to send packet to a disconnected client" {:packet packet})))+                              (try+                                (streams/write-frame!! (encode-packet! packet (req! @state ::phase/phase)) output-stream)+                                (catch Throwable t+                                  (close)+                                  (when-not (instance? SocketException t)+                                    (throw t)))))+              ::receive-packet (fn []+                                 (when (Socket/.isClosed socket)+                                   (throw (Exception. "Tried to read packet from a disconnected client")))+                                 (try+                                   (let [frame (streams/read-frame!! input-stream)+                                         {::phase/keys! [phase]} @state+                                         packet (decode-packet! frame phase)]+                                     (when-let [{::pk/keys! [id]} packet]+                                       (case id+                                         ::serverbound/handshaking        (swap! state assoc ::phase/phase (req! packet ::phase/phase))+                                         ::serverbound/login-acknowledged (swap! state assoc ::phase/phase ::phase/config)+                                         ::serverbound/finish-config      (swap! state assoc ::phase/phase ::phase/play)+                                         ::serverbound/login-start+                                         (let [{:keys! [username uuid]} packet]+                                           (swap! state assoc ::player/uuid uuid))+                                         nil)+                                       (merge packet (select-keys @state [::player/uuid]))))+                                   (catch Throwable t+                                     (close)+                                     (when-not (or (instance? SocketException t) (instance? EOFException t))+                                       (throw t)))))}]     (io-thread       (loop []-        (when (= ::not-closed (deref closed-promise 0 ::not-closed))-          (<!! (timeout 15000))-          (when (#{::phase/config ::phase/play} (::phase/phase @state))-            (put! clientbound-packets-                  {::pk/id ::clientbound/keep-alive-                   :id (rand-int Integer/MAX_VALUE)}))-          (recur))))--    (io-thread-      (try-        (loop []-          (when-let [packet (handle-serverbound-frame! state conn (streams/read-frame!! input-stream))]-            (put! serverbound-packets packet))-          (recur))-        (catch EOFException _)-        (catch SocketException _)-        (finally-          (close! serverbound-packets)-          (deliver closed-promise (@state ::player/uuid))-          (Socket/.close socket))))--    (io-thread-      (try-        (loop []-          (when-some [packet (<!! clientbound-packets)]-            (streams/write-frame!! (encode-packet! packet (req! @state ::phase/phase)) output-stream)-            (recur)))-        (catch SocketException _)-        (finally-          (close! clientbound-packets))))+        (Thread/sleep 15000)+        (when (#{::phase/config ::phase/play} (::phase/phase @state))+          ((::send-packet conn)+           {::pk/id ::clientbound/keep-alive+            :id (rand-int Integer/MAX_VALUE)}))+        (recur)))     conn))