connections.clj

Bowmap · bowmap.git · Tickets

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

(ns net.bowmap.server.runtime.connections
  (:require
   [net.bowmap.server.game.handle :as handle]
   [net.bowmap.server.network.connection :as connection]
   [net.bowmap.server.network.server :as server]
   [net.bowmap.server.protocol.packet :as packet]
   [net.bowmap.server.protocol.packet-serialization :as serialize]
   [net.bowmap.server.protocol.phase :as phase]
   [net.bowmap.server.protocol.serverbound-packets :as serverbound]))

(defn apply-packet
  "Returns the value a client should take on when handling 'packet'."
  [client packet]
  (let [{::packet/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'))
          (let [packets (handle/handle-packet connection-uuid packet)]
            (run! send-packet! packets)))
        (recur)))))

(defn handle-connections!
  [server]
  (loop []
    (let [connection (server/accept-connection!! server)]
      (Thread/startVirtualThread
        #(handle-connection! connection))
      (recur))))