4e07f38
Branches > main > 4e07f38 > files
Keep track of state with a relational data structure
Commit: 4e07f384b215c73a1f29c48738b06b3db1cadf2b
Parent: 0d6765e
4 changed files:
deps.edn view file
@@ -12,5 +12,5 @@ nrepl/nrepl {:mvn/version "1.7.0"} dev.weavejester/medley {:mvn/version "1.10.0"} org.clojure/data.json {:mvn/version "2.5.2"}- datascript/datascript {:mvn/version "1.8.1"}+ com.wotbrew/relic {:mvn/version "0.1.7"} io.netty/netty-buffer {:mvn/version "4.1.111.Final"}}}src/net/bowmap/server/game/handle.clj view file
@@ -1,6 +1,6 @@ (ns net.bowmap.server.game.handle (:require- [datascript.core :as d]+ [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]@@ -12,45 +12,50 @@ [net.bowmap.server.protocol.serverbound-packets :as serverbound])) (defmulti handle-packet- "Handles a packet from a player given their connection uuid.- Returning a sequence of response packets."- (fn [connection-uuid 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 :default [_ _ _]) -(defmethod handle-packet ::serverbound/status-request [_ _]- [{::packet/id ::clientbound/status-response+(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 0+ ::p/online-player-count (count (state ::server/players)) ::p/max-player-count 1000}]) -(defmethod handle-packet ::serverbound/ping-request [_ {::p/keys! [timestamp]}]- [{::packet/id ::clientbound/pong-response+(defmethod handle-packet ::serverbound/ping-request [_ _ {::p/keys! [timestamp]}]+ [nil+ {::packet/id ::clientbound/pong-response ::p/timestamp timestamp}]) -(defmethod handle-packet ::serverbound/login-start [connection-uuid {::p/keys! [uuid username]}]- (d/transact! server/conn- [{::player/uuid uuid- ::player/username username- ::connection/connection-uuid connection-uuid}])-- [{::packet/id ::clientbound/login-success+(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 [_ _]- [{::packet/id ::clientbound/known-packs+(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 [_ {::p/keys! [known-packs]}]+(defmethod handle-packet ::serverbound/known-packs [state _ {::p/keys! [known-packs]}] (if (= [registry/core-data-pack] known-packs)- (conj registry/registry-packets- {::packet/id ::clientbound/finish-config})+ (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}))))src/net/bowmap/server/game/server.clj view file
@@ -1,11 +1,15 @@ (ns net.bowmap.server.game.server (:require- [datascript.core :as d]- [net.bowmap.server.game.player :as player]- [net.bowmap.server.network.connection :as connection]))+ [clojure.spec.alpha :as s]+ [com.wotbrew.relic :as relic]+ [net.bowmap.server.game.player :as player])) -(def schema- {::player/uuid {:db/unique :db.unique/identity}- ::connection/connection-uuid {:db/unique :db.unique/identity}})+(s/def ::players (s/coll-of ::player/player :kind set?))+(s/def ::server (s/keys :opt [::players])) -(defonce conn (d/create-conn schema))+(def players-by-uuid+ [[:from ::players]+ [:unique ::player/uuid]])++(defonce state (atom (relic/mat {}+ players-by-uuid)))src/net/bowmap/server/runtime/connections.clj view file
@@ -3,6 +3,7 @@ [net.bowmap.server.game.handle :as handle] [net.bowmap.server.network.connection :as connection] [net.bowmap.server.network.server :as server]+ [net.bowmap.server.game.server :as state] [net.bowmap.server.protocol.packet :as packet] [net.bowmap.server.protocol.packet-serialization :as serialize] [net.bowmap.server.protocol.phase :as phase]@@ -30,8 +31,11 @@ packet (serialize/decode-frame client frame) client' (apply-packet client packet)] (assert (compare-and-set! client-atom client client'))- (let [packets (handle/handle-packet connection-uuid packet)]- (run! send-packet! packets)))+ (loop [state @state/state]+ (let [[state' & packets] (handle/handle-packet state connection-uuid packet)]+ (if (or (nil? state') (compare-and-set! state/state state state'))+ (run! send-packet! packets)+ (recur @state/state))))) (recur))))) (defn handle-connections!