core.clj
Branches > namespace-reorganization > 52f154f > files / src / net / bowmap / core.clj
(ns net.bowmap.core
(:require
[aleph.tcp :as tcp]
[manifold.deferred :as d]
[manifold.stream :as s]
[net.bowmap.client.state :as state]
[net.bowmap.packet-handling :as handle]
[net.bowmap.packet.client :refer [encode-packet]]
[net.bowmap.packet.read :as read]
[net.bowmap.packet.server :as sp])
(:import
[io.netty.bootstrap ServerBootstrap]
[io.netty.buffer ByteBuf Unpooled]
[io.netty.channel ChannelOption]))
(defn packet-framer-xf
"Frames bytes from incoming byte arrays and calls 'xf' on ByteBufs of
complete Minecraft protocol packet bytes."
[rf]
(let [buf (Unpooled/buffer)]
(fn
([] (rf))
([res] (rf res))
([res input]
(ByteBuf/.writeBytes buf input)
(loop [res res]
(if (read/can-read-packet? buf)
(let [len (read/read-varint! buf)
;; This copy is probably inefficient but fine for now.
res' (rf res (ByteBuf/.copy (ByteBuf/.readRetainedSlice buf len)))]
(ByteBuf/.discardReadBytes buf)
(recur res'))
res))))))
(defn handle-packet
"Handles one framed Minecraft protocol packet bytes."
[client packet-buf]
(let [{:keys [client response]} (handle/response client (sp/decode-packet packet-buf (::state/state client)))]
(doseq [pk response]
(s/put! (::stream client) (encode-packet pk (::state/state client))))
client))
(defn client-handler [stream _]
(let [client {::state/state ::state/handshaking
::stream stream}]
(d/catch (s/reduce #'handle-packet client (s/transform packet-framer-xf stream))
(fn [e]
(println "Exception in client packets:" e)))))
(defn start-server! []
(tcp/start-server #'client-handler
{:port 25565
:bootstrap-transform #(ServerBootstrap/.childOption % ChannelOption/TCP_NODELAY true)}))
(defn -main [& _args]
(start-server!)
(println "Server Started"))
(comment
(require 'dev.grahp.bytebuf)
(def server (start-server!))
(.close server))