handle.clj

Bowmap · bowmap.git · Tickets

Branches > main > 7bcccfb > files / src / net / bowmap / server / game / handle.clj

(ns net.bowmap.server.game.handle
  (:require
   [com.wotbrew.relic :as rel]
   [net.bowmap.server.game.player :as player]
   [net.bowmap.server.game.server :as server]
   [net.bowmap.server.network.connection :as connection]
   [net.bowmap.server.protocol.clientbound-packets :as clientbound]
   [net.bowmap.server.protocol.component :as component]
   [net.bowmap.server.protocol.packet :as packet]
   [net.bowmap.server.protocol.registry :as registry]
   [net.bowmap.server.protocol.schema :as p]
   [net.bowmap.server.protocol.serverbound-packets :as serverbound]))

(defmulti handle-packet
  "Handles a packet from a player given their connection uuid. Takes the game
   state, and returns a vector of nil or a state value, followed by 0 or more
   response packets."
  (fn [state connection-uuid packet]
    (::packet/id packet)))

(defmethod handle-packet :default [_ _ _])

(defmethod handle-packet ::serverbound/status-request [state _ _]
  [nil
   {::packet/id ::clientbound/status-response
    ::p/version-name "26.3"
    ::p/protocol 777
    ::p/motd {::component/text "Bowmap!"
              ::component/color "#9f9f9f"}
    ::p/online-player-count (count (state ::server/players))
    ::p/max-player-count 1000}])

(defmethod handle-packet ::serverbound/ping-request [_ _ {::p/keys! [timestamp]}]
  [nil
   {::packet/id ::clientbound/pong-response
    ::p/timestamp timestamp}])

(defmethod handle-packet ::serverbound/login-start [state connection-uuid {::p/keys! [uuid username]}]
  [(rel/transact state
                 [:insert ::server/players
                  {::player/uuid uuid
                   ::player/username username
                   ::connection/connection-uuid connection-uuid}])
   {::packet/id ::clientbound/login-success
    ::p/game-profile {::p/uuid uuid
                      ::p/username username
                      ::p/game-profile-properties []}
    ::p/session-uuid connection-uuid}])

(defmethod handle-packet ::serverbound/login-acknowledged [_ _ _]
  [nil
   {::packet/id ::clientbound/known-packs
    ::p/known-packs [registry/core-data-pack]}])

(defmethod handle-packet ::serverbound/known-packs [state _ {::p/keys! [known-packs]}]
  (if (= [registry/core-data-pack] known-packs)
    (cons state
          (conj registry/registry-packets
                {::packet/id ::clientbound/finish-config}))
    (throw (ex-info "Client does not support the core datapack"
                    {:known-packs known-packs}))))