27afad4

Branches > refactor/use-spec-1 > 27afad4 > files

Remove global state from instance.clj

Grahp, 2026-06-02

Commit: 27afad45f04614a2c4a0c6cefff71382482c4bc7
Parent: 2eb109b

2 changed files:

src/net/bowmap/instance.clj modified (view file)

@@ -12,35 +12,25 @@  ; The logical server, holds a set of clients connected -; TODO Global state D:-(defonce instance (atom {::clients {}-                         ::message-out-channels {}}))--(defonce instance2 (atom {::conections {}}))--(defn send-message! [client msg]-  ; TODO is put! okay?-  (put! ((::message-out-channels @instance) (::client/id client)) msg))--(defn keep-alive! [client]+(defn keep-alive! [messages-out]   (io-thread     (loop []       (<!! (timeout 20000))-      (send-message! client {::msg/id ::cl/keep-alive-                             :id (long (* (rand) Long/MAX_VALUE))})+      (put! messages-out {::msg/id ::cl/keep-alive+                          :id (long (* (rand) Long/MAX_VALUE))})       (recur))))  (defn read-and-handle-packet   "Reads/deserializes one packet into a message, and handles it.    Because packet reading is dependent on the state of the client, and handling a packet can update the state of the client,    Reading and handling must be synchronized!"-  [pk client]+  [pk client messages-out]   (when-some [msg (srv/packet->message pk (::state/connection-state client))]     (let [{:keys [::client/client ::a/keep-alive? ::a/messages]} (a/apply-message msg client)]       (when keep-alive?-        (keep-alive! client))+        (keep-alive! messages-out))       (doseq [msg messages]-        (send-message! client msg))+        (put! messages-out msg))       client)))  (defn handle-packets-and-messages [client packets-in messages-out packets-out]@@ -51,7 +41,7 @@                     client))     packets-in ([pk]                 (when pk-                  (read-and-handle-packet pk client)))))+                  (read-and-handle-packet pk client messages-out)))))  (defn connect! [client packets-in packets-out]   (let [messages-out (chan 1024)]@@ -60,26 +50,22 @@       (loop [client client]         (when-some [client (handle-packets-and-messages client packets-in messages-out packets-out)]           ; Otherwise, stop?-          (swap! instance update ::clients assoc (::client/id client) client)           (recur client))))-    (swap! instance update ::clients assoc (::client/id client) client)-    (swap! instance update ::message-out-channels assoc (::client/id client) messages-out)-    client))+    nil))  (defn client   "Returns a new client value"   []-  ; TODO this state should be server-wide, I think.-  ; ??? What is he on about ^-  {::state/connection-state ::state/handshaking-   ::client/id (random-uuid)})+  {::state/connection-state ::state/handshaking}) -(defn handle-client [packets-in packets-out]-  (let [client (client)]-    (connect! client packets-in packets-out)))--; TODO rename...+; TODO make reloadable, if port is already running, just swap it out? (defn start-server! [{:keys [port]}]-  (server/start-server! {:port port-                         :handler #'handle-client})+  ; Start the client handling loop here+  (let [{::server/keys [server client-chan]} (server/start-server! {:port port})]+    (io-thread+      ; Loop over the instance?+      (loop []+        (when-some [{::server/keys [packets-in packets-out]} (<!! client-chan)]+          (connect! (client) packets-in packets-out)+          (recur)))))   nil)

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

@@ -1,24 +1,28 @@ (ns net.bowmap.network.server   (:require    [aleph.tcp :as tcp]-   [clojure.core.async :refer [chan]]+   [clojure.core.async :refer [chan put!]]    [manifold.stream :as s]    [net.bowmap.network.packet.frame :as frame])   (:import    [io.netty.bootstrap ServerBootstrap]    [io.netty.channel ChannelOption])) -(defn- handle-client [handler stream info]+(defn- handle-client [client-chan stream info]   (let [packets-in (chan 1 frame/packet-framer-xf)         packets-out (chan)]     (s/connect stream packets-in)     (s/connect packets-out stream)-    (handler packets-in packets-out)))+    (put! client-chan {::packets-in packets-in+                       ::packets-out packets-out}))) +; Returns [:server :client-chan]? (defn start-server!   "Starts a Minecraft server at the port, passing clients into the instance."-  [& {:keys [port handler]}]-  (tcp/start-server (fn [stream info]-                      (handle-client handler stream info))-                    {:port port-                     :bootstrap-transform #(ServerBootstrap/.childOption % ChannelOption/TCP_NODELAY true)}))+  [& {:keys [port]}]+  (let [client-chan (chan 64)]+    {::server (tcp/start-server (fn [stream info]+                                  (handle-client client-chan stream info))+                                {:port port+                                 :bootstrap-transform #(ServerBootstrap/.childOption % ChannelOption/TCP_NODELAY true)})+     ::client-chan client-chan}))