core.clj
Branches > namespace-reorganization > abdef62 > files / src / net / bowmap / core.clj
(ns net.bowmap.core
(:require
[aleph.tcp :as tcp]
[manifold.stream :as s]
[net.bowmap.client.state :as state]
[net.bowmap.codecs.read :as read]
[net.bowmap.packet-handling :refer [handle-packet]]
[net.bowmap.packets.client :refer [encode-packet!]]
[net.bowmap.packets.server :as sp])
(:import
[io.netty.buffer ByteBuf Unpooled]
[io.netty.channel ChannelOption]))
;; Document why parsing and handling are done synchronously
(defn read-packet! [bs client]
(let [{::keys [buf]} @client
buf (ByteBuf/.writeBytes buf bs)]
(while (read/can-read-packet? buf)
(prn [(subvec (vec (.array buf))
(.readerIndex buf)
(.writerIndex buf))
(::state/state @client)])
;; TODO handle exceptions?
(let [{:keys [::state/state response]} (handle-packet (sp/decode-packet! buf (::state/state @client))
client)]
(when state
(vswap! client assoc ::state/state state))
(when response
;; TODO this can also throw...
(encode-packet! response (::state/state @client))))
(ByteBuf/.discardReadBytes buf))))
(defn client-handler [s _]
(let [client (volatile! {::state/state ::state/handshaking
::buf (Unpooled/buffer)})]
(s/consume (fn [bs] (read-packet! bs client))
s)))
(defn start-server! []
(tcp/start-server #'client-handler
{:port 25565
:bootstrap-transform (fn [bootstrap]
(.childOption bootstrap ChannelOption/TCP_NODELAY true)
bootstrap)}))
(defn -main [& _args]
(start-server!)
(println "Server Started"))
(comment
(.close server)
(def server (start-server!)))