connections.clj

Bowmap · bowmap.git · Tickets

Branches > main > c559409 > files / src / net / bowmap / server / runtime / connections.clj

(ns net.bowmap.server.runtime.connections
  (:require
   [clojure.core.async :refer [io-thread]]
   [net.bowmap.server.game.handle :as handle]
   [net.bowmap.server.game.server :as state]
   [net.bowmap.server.network.connection :as connection]
   [net.bowmap.server.network.server :as server]
   [net.bowmap.server.packet.phase :as phase]
   [net.bowmap.server.packet.schema :as p]
   [net.bowmap.server.packet.serialize :as serialize]
   [net.bowmap.server.packet.serverbound :as serverbound]))

(defn apply-packet
  "Returns the value a client should take on when handling 'packet'."
  [client packet]
  (let [{::p/keys! [id]} packet]
    (case id
      ::serverbound/handshaking (assoc client ::phase/phase (req! packet ::phase/phase))
      ::serverbound/login-acknowledged (assoc client ::phase/phase ::phase/config)
      ::serverbound/finish-config (assoc client ::phase/phase ::phase/play)
      client)))

(defn handle-connection! [connection]
  (let [client-atom (atom {::phase/phase ::phase/handshaking})
        connection-uuid (random-uuid)
        send-packet! (fn [packet]
                       (let [frame (serialize/encode-packet @client-atom packet)]
                         (connection/send-frame! connection frame)))]
    (loop []
      (when-some [frame (connection/receive-frame!! connection)]
        (let [client @client-atom
              packet (serialize/decode-frame client frame)
              client' (apply-packet client packet)]
          (assert (compare-and-set! client-atom client client'))
          (loop [state @state/state]
            (let [[state' & packets] (handle/handle-packet state connection-uuid packet)]
              (if (or (nil? state') (compare-and-set! state/state state state'))
                (run! send-packet! packets)
                (recur @state/state)))))
        (recur)))))

(defn handle-connections!
  [server]
  (loop []
    (let [connection (server/accept-connection!! server)]
      (io-thread
        (handle-connection! connection))
      (recur))))