connections.clj
Branches > main > 0d6765e > 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))))