server.clj

Branches > facts > 4b8254b > files / src / net / bowmap / protocol / server.clj

(ns net.bowmap.protocol.server
  (:require
   [clojure.core.async :refer [<!! >!! alt!! io-thread put!]]
   [net.bowmap.protocol.client :as client]
   [net.bowmap.protocol.handle :as handle]
   [net.bowmap.protocol.packet.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)
          {::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] :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))))
                                    (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"))))))
        (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))))