2ba13a7
Branches > main > 2ba13a7 > files / src / net / bowmap / server / core.clj
Add login and play packets to new client handling
Commit: 2ba13a700f8a6862b24b82e15ab891abf71c0534
Parent: 083e2e7
1 changed file:
src/net/bowmap/network/handle.clj view file
@@ -1,10 +1,15 @@ (ns net.bowmap.network.handle (:require+ [net.bowmap.network.chunk :as chunk] [net.bowmap.network.client :refer [send-packet!]] [net.bowmap.network.packet :as pk] [net.bowmap.network.packets.clientbound :as clientbound]+ [net.bowmap.network.packets.registry :as registry] [net.bowmap.network.packets.serverbound :as serverbound]+ [net.bowmap.network.registry :as reg] [net.bowmap.network.state :as state]+ [net.bowmap.server.entity :as entity]+ [net.bowmap.server.gamemode :as gamemode] [net.bowmap.server.server :as server])) (defmulti handle-packet@@ -12,13 +17,15 @@ (::pk/id packet))) (defmethod handle-packet :default [client _]- {:client client})+ {:client client+ :packets []}) (defmethod handle-packet ::serverbound/handshaking [client pk] (let [{:keys! [intent protocol]} pk] {:client (assoc client ::state/connection-state intent- :protocol-id protocol)}))+ :protocol-id protocol)+ :packets []})) ; TODO move to a fact and the game logic handler :) (defmethod handle-packet ::serverbound/status-request [client _]@@ -33,8 +40,143 @@ :description {:text "Bowmap!"} :enforcesSecureChat false}}]}) +(defmethod handle-packet ::serverbound/ping-request [client pk]+ {:client client+ :packets [{::pk/id ::clientbound/pong-response+ :timestamp (:timestamp pk)}]})++(defmethod handle-packet ::serverbound/login-start [client pk]+ (let [{:keys! [uuid username]} pk]+ {:client (assoc client ::entity/uuid uuid)+ :packets [{::pk/id ::clientbound/login-success+ :profile {:uuid uuid+ :username username+ :properties []}+ :session-id (random-uuid)}]}))++(defmethod handle-packet ::serverbound/login-acknowledged [client _]+ {:client (assoc client ::state/connection-state ::state/config)+ :packets [{::pk/id ::clientbound/known-packs+ ;; TODO also probably good to unbundle this+ :known-packs [{:namespace "minecraft"+ :id "core"+ :version "26.2"}]}]})++; TODO how to update state here?+; Yield facts from this as well and send 'em in!+; Or well, this can be retried so just use the dosync+(defmethod handle-packet ::serverbound/known-packs [client _]+ {:client client+ :packets (conj (vec (registry/registry-packets))+ {::pk/id ::clientbound/update-tags+ :tagged-registries [{:registry "minecraft:block"+ :tags [{:tag-name "bowmap:infiniburn"+ :entries []}]}]}++ {::pk/id ::clientbound/update-tags+ :tagged-registries [{:registry "minecraft:damage_type"+ :tags [{:tag-name "minecraft:is_fire"+ :entries []}+ {:tag-name "minecraft:is_explosion"+ :entries []}+ {:tag-name "minecraft:bypasses_shield"+ :entries []}]}]}++ {::pk/id ::clientbound/update-tags+ :tagged-registries [{:registry "minecraft:banner_pattern"+ :tags [{:tag-name "minecraft:pattern_item/bordure_indented" :entries []}+ {:tag-name "minecraft:pattern_item/creeper" :entries []}+ {:tag-name "minecraft:pattern_item/field_masoned" :entries []}+ {:tag-name "minecraft:pattern_item/flow" :entries []}+ {:tag-name "minecraft:pattern_item/flower" :entries []}+ {:tag-name "minecraft:pattern_item/globe" :entries []}+ {:tag-name "minecraft:pattern_item/guster" :entries []}+ {:tag-name "minecraft:pattern_item/mojang" :entries []}+ {:tag-name "minecraft:pattern_item/piglin" :entries []}+ {:tag-name "minecraft:pattern_item/skull" :entries []}]}]}++ {::pk/id ::clientbound/finish-config})})+++(defn- build-chunk-packets []+ (let [pk {::pk/id ::clientbound/chunk-data-and-update-light+ :chunk-data+ (let [stone {:block-count (* 16 16 16)+ :fluid-count 0+ :block-states {:bpe 0+ :palatte 1}+ :biomes {:bpe 0+ :palatte 0}}+ air {:block-count 0+ :fluid-count 0+ :block-states {:bpe 0+ :palatte 0}+ :biomes {:bpe 0+ :palatte 0}}]+ {:data (cons stone (repeat (- chunk/world-height-chunk-sections 1) air))})+ :light-data {}}]+ (for [x (range -16 17)+ z (range -16 17)]+ (assoc pk+ :chunk-x x+ :chunk-z z))))++(defmethod handle-packet ::serverbound/finish-config [client _]+ (let [entity-id (entity/next-entity-id!)+ uuid (req! client ::entity/uuid)+ client (assoc client+ ::state/connection-state ::state/play+ ::entity/id entity-id)+ player {::entity/id entity-id+ ::entity/uuid uuid}]+ ; Bad state here, yield a fact instead, but that's later ofc+ (dosync+ (if (@server/players uuid)+ (throw (Exception. "Player tried to join with an existing UUID"))+ (commute server/players assoc uuid player)))+ {:client client+ :packets (-> [{::pk/id ::clientbound/login+ :entity-id entity-id+ :hardcore? false+ ; TODO use the registry id, show that connection somehow because this is a reference to that id+ :dimension-names [reg/world-dimension]+ :max-players server/max-player-count+ :view-distance 32+ :simulation-distance 32+ :reduced-debug-info? false+ :enable-respawn-screen? false+ :do-limited-crafting? false+ :dimension-type-id reg/world-dimension-id+ :dimension-name reg/world-dimension+ :hashed-seed 203894+ :gamemode ::gamemode/adventure+ :debug-world? false+ :superflat-world? true+ :has-death-location? false+ :portal-cooldown 10+ :sea-level 60+ :online-mode? false+ :enforce-secure-chat? true}+ {::pk/id ::clientbound/game-event+ :event :wait-for-chunks}]+ (into (build-chunk-packets))+ (conj {::pk/id ::clientbound/synchronize-player-position+ :teleport-id (rand-int Integer/MAX_VALUE)+ :x 0+ :y 16+ :z 0+ :velocity-x 0+ :velocity-y 0+ :velocity-z 0+ :yaw 0+ :pitch 0+ :flags #{}}))}))+++; TODO keepalive+ (defn handle!! [client-ref packet]- (let [{:keys [client packets]} (handle-packet @client-ref packet)]+ (let [{:keys! [client packets]} (handle-packet @client-ref packet)] (dosync (ref-set client-ref client)) (doseq [pk packets]