packet_handling.clj

Branches > client-handling-rewrite > c1ef72f > files / src / net / bowmap / packet_handling.clj

(ns net.bowmap.packet-handling
  (:require
   [net.bowmap.network.state :as state]
   [net.bowmap.network.message :as msg]
   [net.bowmap.network.message.client :as client]
   [net.bowmap.network.registry :as registry]
   [net.bowmap.network.message.server :as server]))

; "packet handling" is inherently about the low-level protocol level, so either handle stuff at a low level or turn
; packets into high level game events to be sent somewhere else

(defmulti handle-packet
  (fn [msg client]
    (::msg/id msg)))

; Should return just a client...
; Should be a much better interface as well
; Basically sending a packet into the server?
(defn response
  "Returns a map of a client, and any other keys a packet handler may use.
   Client may be unchanged, or adorned with any information, such as a new state."
  [client msg]
  (let [response (handle-packet msg client)]
    (if (:client response)
      response
      (assoc response :client client))))

(defmethod handle-packet :default [msg client]
  (prn "Unhandled message:" msg))

(defmethod handle-packet ::server/handshaking [msg client]
  {:client (assoc client ::state/state (:intent msg))})

(defmethod handle-packet ::server/status-request [msg client]
  {:response [{::msg/id ::client/status-response
               ;; Should be un-bundled yeah.
               :response {:version {:name "1.21.11"
                                    :protocol 774}
                          :players {:online 0
                                    :max 1000}
                          ; Is this a text component? Could make that interface
                          :description {:text "Bowmap!"}
                          :enforcesSecureChat false}}]})

(defmethod handle-packet ::server/ping-request [msg client]
  {:response [{::msg/id ::client/pong-response
               :timestamp (:timestamp msg)}]})

(defmethod handle-packet ::server/login-start [msg client]
  {:response [{::msg/id ::client/login-success
               :uuid (:uuid msg)
               :username (:username msg)
               :properties []}]})

(defmethod handle-packet ::server/login-acknowledged [msg client]
  {:client (assoc client ::state/state ::state/config)
   :response [{::msg/id ::client/known-packs
               ;; TODO also probably good to unbundle this
               :known-packs [{:namespace "minecraft" :id "core" :version "1.12.11"}]}]})

(defmethod handle-packet ::server/known-packs [msg client]
  {:response (conj (vec registry/registry-packets)
                   {::msg/id ::client/finish-config})})

(defmethod handle-packet ::server/finish-config [msg client]
  {:client (assoc client ::state/state ::state/play)
   :keepalive true
   :response [{::msg/id ::client/login
              :entity-id 0 ;; TODO magic zero :p
              :hardcore? false
              :dimension-names ["world"]
              :max-players 1000
              :view-distance 32
              :simulation-distance 32
              :reduced-debug-info? false
              :enable-respawn-screen? false
              :do-limited-crafting? false
              :dimension-type-id 0
              :dimension-name "world"
              :hashed-seed 203894
              :gamemode :creative
              :previous-gamemode :unknown
              :debug-world? false
              :superflat-world? true
              :has-death-location? false
              :portal-cooldown 10
              :sea-level 60
              :enforce-secure-chat? true}
              {::msg/id ::client/game-event
               :event :wait-for-chunks}]})