b6d3d26

Bowmap · bowmap.git · Tickets

Branches > main > b6d3d26 > files

Send Login (Play) to client

Grahp, 2026-10-05

Commit: b6d3d26f475aa28c88e87b263f548644ce45c2f9
Parent: 7bcccfb

9 changed files:

src/net/bowmap/server/game/handle.clj modified (view file)

@@ -6,9 +6,12 @@    [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.entity :as entity]+   [net.bowmap.server.protocol.gamemode :as gamemode]    [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.schema.minecraft :as mc]    [net.bowmap.server.protocol.serverbound-packets :as serverbound]))  (defmulti handle-packet@@ -28,7 +31,7 @@     ::p/motd {::component/text "Bowmap!"               ::component/color "#9f9f9f"}     ::p/online-player-count (count (state ::server/players))-    ::p/max-player-count 1000}])+    ::p/max-player-count server/max-player-count}])  (defmethod handle-packet ::serverbound/ping-request [_ _ {::p/keys! [timestamp]}]   [nil@@ -59,3 +62,25 @@                 {::packet/id ::clientbound/finish-config}))     (throw (ex-info "Client does not support the core datapack"                     {:known-packs known-packs}))))++(defmethod handle-packet ::serverbound/finish-config [state connection-uuid _]+  (let [entity-id (entity/next-entity-id)]+    [(rel/transact state+                   [:update ::server/players+                    {::server/playing? true+                     ::entity/id entity-id}+                    [= ::connection/connection-uuid connection-uuid]])+     {::packet/id ::clientbound/login+      ::entity/id entity-id+      :dimensions [registry/world-dimension]+      ::p/max-player-count server/max-player-count+      :render-distance 32+      :simulation-distance 32+      :current-dimension-registry-id (registry/registry-id ::mc/dimension_type registry/world-dimension)+      :current-dimension registry/world-dimension+      :first-8-bytes-of-the-sha-256-hash-of-the-world's-seed 0+      ::gamemode/gamemode ::gamemode/adventure+      :superflat-world? true+      :portal-cooldown-ticks 0+      :sea-level 60+      :enforce-secure-chat? true}]))

src/net/bowmap/server/game/server.clj modified (view file)

@@ -4,6 +4,8 @@    [com.wotbrew.relic :as relic]    [net.bowmap.server.game.player :as player])) +(def max-player-count 1000)+ (s/def ::players (s/coll-of ::player/player :kind set?)) (s/def ::server (s/keys :opt [::players])) 

src/net/bowmap/server/protocol/block.clj added (view file)

@@ -0,0 +1,8 @@+(ns net.bowmap.server.protocol.block+  (:require+   [clojure.spec.alpha :as s]))++(s/def ::x int?)+(s/def ::y int?)+(s/def ::z int?)+(s/def ::location (s/keys :opt [::x ::y ::z]))

src/net/bowmap/server/protocol/clientbound_packets.clj modified (view file)

@@ -1,5 +1,7 @@ (ns net.bowmap.server.protocol.clientbound-packets   (:require+   [net.bowmap.server.protocol.entity :as entity]+   [net.bowmap.server.protocol.gamemode :as gamemode]    [net.bowmap.server.protocol.phase :as phase]    [net.bowmap.server.protocol.schema :as p]    [net.bowmap.server.protocol.writers :refer :all]))@@ -98,7 +100,29 @@     ::world-event nil     ::particle nil     ::update-light nil-    ::login nil+    ::login (map> ::entity/id int>+                  :hardcore? boolean>+                  :dimensions (list> identifier>)+                  ::p/max-player-count varint>+                  :render-distance varint>+                  :simulation-distance varint>+                  :reduced-debug-info? boolean>+                  :use-respawn-screen? boolean>+                  :do-limited-crafting? boolean>+                  :current-dimension-registry-id varint>+                  :current-dimension identifier>+                  :first-8-bytes-of-the-sha-256-hash-of-the-world's-seed long>+                  ::gamemode/gamemode (enum> varint> {0 ::gamemode/survival 1 ::gamemode/creative 2 ::gamemode/adventure 3 ::gamemode/spectator})+                  :previous-gamemode (enum> varint> {0 nil 1 ::gamemode/survival 2 ::gamemode/creative 3 ::gamemode/adventure 4 ::gamemode/spectator})+                  :debug-world? boolean>+                  :superflat-world? boolean>+                  :has-death-location? boolean>+                  :death-dimension-name (context-optional> identifier>)+                  :death-location (context-optional> block-location>)+                  :portal-cooldown-ticks varint>+                  :sea-level varint>+                  :online? boolean>+                  :enforce-secure-chat? boolean>)     ::low-disk-space-warning nil     ::map-data nil     ::merchant-offers nil

src/net/bowmap/server/protocol/entity.clj added (view file)

@@ -0,0 +1,9 @@+(ns net.bowmap.server.protocol.entity)++(defonce highest-entity-id (atom 0))++(defn next-entity-id+  "Returns the next highest available entity ID.+   Entity IDs are unique used in the protocol to refer to entities."+  []+  (swap! highest-entity-id inc))

src/net/bowmap/server/protocol/gamemode.clj added (view file)

@@ -0,0 +1,5 @@+(ns net.bowmap.server.protocol.gamemode+  (:require+   [clojure.spec.alpha :as s]))++(s/def ::gamemode #{::survival ::creative ::adventure ::spectator})

src/net/bowmap/server/protocol/registry.clj modified (view file)

@@ -304,6 +304,9 @@ (defonce registry-ids->values (update-vals registry #(zipmap (range) (keys %)))) (defonce registry-values->ids (update-vals registry-ids->values set/map-invert)) +(defn registry-id [registry value]+  (req! (registry-values->ids registry) value))+ (let [registry-packets       (for [[registry-id entries] registry]         {::packet/id ::clientbound/registry-data

src/net/bowmap/server/protocol/serverbound_packets.clj modified (view file)

@@ -27,7 +27,7 @@    [::client-information nil     ::cookie-response nil     ::plugin-message nil-    ::finish-config nil+    ::finish-config (map<)     ::keep-alive nil     ::pong nil     ::resource-pack-response nil

src/net/bowmap/server/protocol/writers.clj modified (view file)

@@ -4,11 +4,13 @@    See https://minecraft.wiki/w/Java_Edition_protocol/Packets#Data_types"   (:require    [clojure.data.json :as json]+   [clojure.set :as set]    [clojure.spec.alpha :as s]+   [net.bowmap.server.protocol.block :as block]    [net.bowmap.server.protocol.buffer :as buffer]    [net.bowmap.server.protocol.identifier :as identifier]-   [net.bowmap.server.protocol.schema :as p]-   [net.bowmap.server.protocol.nbt :as nbt])+   [net.bowmap.server.protocol.nbt :as nbt]+   [net.bowmap.server.protocol.schema :as p])   (:import    [java.nio.charset StandardCharsets]    [java.util UUID]))@@ -188,6 +190,31 @@                                 ::p/game-profile-property-value (string> 32767)                                 ::p/game-profile-property-signature (optional> (string> 1024))))) +(defn enum>+  "Returns a writer that writes one of a set of values via 'writer'.+   Takes a map of encoded values to decoded values (values that will appear in+   the packet map), same as the enum reader. For example, the map {1 :foo}+   will write 1 (via 'writer') when given :foo, so the map is 'backwards'.+   When the value is not in the enum map, calls 'writer' with nil."+  [writer m]+  (let [m (set/map-invert m)]+    (fn [buf x]+      (writer buf (m x)))))++(defn block-location>+  "Writes a block location as a 64-bit integer made of 3 signed integers: 26+   bits for the x, 26 bits for the y, and 16 bits for the z. Throws if any+   of the coordinates do not fit within their respective integer sizes."+  [buf {::block/keys! [x y z]}]+  {:pre [(<= (Math/pow -2 25) x (- (Math/pow 2 25) 1))+         (<= (Math/pow -2 25) z (- (Math/pow 2 25) 1))+         (<= (Math/pow -2 11) y (- (Math/pow 2 11) 1))]}+  (long> buf+         (bit-or+           (bit-shift-left (bit-and x 0x3FFFFFF) 38)+           (bit-shift-left (bit-and z 0x3FFFFFF) 12)+           (bit-and y 0xFFF))))+ (defn- utf-16-code-units [s]   (map int (String/.toCharArray s)))