server.clj
Branches > main > c97d3bd > files / src / net / bowmap / protocol / server.clj
(ns net.bowmap.protocol.server
(:require
[clojure.core.async :refer [<!! >!! alt!! chan io-thread put! timeout]]
[net.bowmap.protocol.client :as client]
[net.bowmap.protocol.handle :as handle]
[net.bowmap.protocol.packet :as pk]
[net.bowmap.protocol.packet.clientbound :as clientbound :refer [encode-packet!]]
[net.bowmap.protocol.packet.serverbound :refer [decode-packet!]]
[net.bowmap.protocol.state :as state]
[net.bowmap.server.logic :as logic]
[net.bowmap.stormbow.effect-execution :refer [execute-effects!]]
[net.bowmap.transport.connection :as connection]
[net.bowmap.transport.server :as mc]))
(defn handle-connection [connection]
(io-thread
(let [client (client/client connection)
clientbound-packets (req! client ::client/clientbound-packets)
keep-alive (chan)
{::connection/keys! [serverbound-frames clientbound-frames close-fn]} connection]
(try
(loop [client client]
(alt!!
serverbound-frames ([frame]
(when (some? frame)
(let [packet (decode-packet! frame (::state/connection-state client))
{:keys [client packets facts keep-alive?] :or {:client client}} (handle/handle-packet client packet)]
; TODO probably want to clean up this side effecting stuff
(doseq [pk packets]
(put! clientbound-packets pk))
(doseq [fact facts]
(execute-effects! (map #(assoc % ::client/client client) (logic/handle-fact fact))))
(when keep-alive?
(put! keep-alive true))
(recur client))))
clientbound-packets ([packet]
(if (some? packet)
(do (>!! clientbound-frames (encode-packet! packet (::state/connection-state client)))
(recur client))
(throw (Exception. "Clientbound packets was closed idk why"))))
keep-alive ([x]
(when x
(put! clientbound-packets {::pk/id ::clientbound/keep-alive
:id (rand-int Integer/MAX_VALUE)})
(io-thread
(<!! (timeout 20000))
(put! keep-alive true)))
(recur client))))
(finally
; TODO Send player disconnected fact, and update the player list from that
(close-fn))))))
(defn start-server! [port]
(let [connections (mc/start-server! port)]
(loop []
(when-let [connection (<!! connections)]
(handle-connection connection))
(recur))))